grain-tools 0.10.21 → 0.10.22

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.
@@ -59,7 +59,20 @@ function publishDaemonEndpoint(configDir, record2) {
59
59
  try {
60
60
  fs.writeFileSync(sibling, `${JSON.stringify(payload, null, 2)}
61
61
  `, { mode: 384 });
62
- fs.renameSync(sibling, target);
62
+ for (let attempt = 1; ; attempt += 1) {
63
+ try {
64
+ fs.renameSync(sibling, target);
65
+ break;
66
+ } catch (error52) {
67
+ const code = error52.code;
68
+ if (!code || !TRANSIENT_RENAME_ERRORS.has(code) || attempt >= RENAME_ATTEMPTS) {
69
+ throw error52;
70
+ }
71
+ if (typeof Atomics !== "undefined" && typeof SharedArrayBuffer !== "undefined") {
72
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, RENAME_RETRY_DELAY_MS);
73
+ }
74
+ }
75
+ }
63
76
  } catch (e2) {
64
77
  try {
65
78
  fs.unlinkSync(sibling);
@@ -103,7 +116,7 @@ function removeDaemonEndpoint(configDir) {
103
116
  } catch {
104
117
  }
105
118
  }
106
- var fs, path, DAEMON_ENDPOINT_FILENAME, DAEMON_ENDPOINT_SCHEMA_VERSION, GRAIN_NOT_INSTALLED_MESSAGE, publishSeq;
119
+ var fs, path, DAEMON_ENDPOINT_FILENAME, DAEMON_ENDPOINT_SCHEMA_VERSION, GRAIN_NOT_INSTALLED_MESSAGE, publishSeq, TRANSIENT_RENAME_ERRORS, RENAME_ATTEMPTS, RENAME_RETRY_DELAY_MS;
107
120
  var init_daemonEndpointFile = __esm({
108
121
  "src/common/daemonEndpointFile.ts"() {
109
122
  "use strict";
@@ -113,6 +126,9 @@ var init_daemonEndpointFile = __esm({
113
126
  DAEMON_ENDPOINT_SCHEMA_VERSION = 1;
114
127
  GRAIN_NOT_INSTALLED_MESSAGE = "Grain is not set up on this machine yet. Run `grain install` to set it up.";
115
128
  publishSeq = 0;
129
+ TRANSIENT_RENAME_ERRORS = /* @__PURE__ */ new Set(["EPERM", "EACCES", "EBUSY", "EEXIST"]);
130
+ RENAME_ATTEMPTS = 5;
131
+ RENAME_RETRY_DELAY_MS = 10;
116
132
  }
117
133
  });
118
134
 
@@ -16945,6 +16961,40 @@ var init_stdio2 = __esm({
16945
16961
  }
16946
16962
  });
16947
16963
 
16964
+ // src/server/bridge/agentGone.ts
16965
+ function watchAgentGone(onGone, options = {}) {
16966
+ const stdin = options.stdin ?? process.stdin;
16967
+ const getParentPid = options.getParentPid ?? (() => process.ppid);
16968
+ const originalParent = getParentPid();
16969
+ let fired = false;
16970
+ const fire = () => {
16971
+ if (!fired) {
16972
+ fired = true;
16973
+ stop2();
16974
+ onGone();
16975
+ }
16976
+ };
16977
+ const timer = setInterval(() => {
16978
+ if (getParentPid() !== originalParent) {
16979
+ fire();
16980
+ }
16981
+ }, options.intervalMs ?? 5e3);
16982
+ timer.unref?.();
16983
+ stdin.on("end", fire);
16984
+ stdin.on("close", fire);
16985
+ function stop2() {
16986
+ clearInterval(timer);
16987
+ stdin.off("end", fire);
16988
+ stdin.off("close", fire);
16989
+ }
16990
+ return stop2;
16991
+ }
16992
+ var init_agentGone = __esm({
16993
+ "src/server/bridge/agentGone.ts"() {
16994
+ "use strict";
16995
+ }
16996
+ });
16997
+
16948
16998
  // node_modules/content-type/index.js
16949
16999
  var require_content_type = __commonJS({
16950
17000
  "node_modules/content-type/index.js"(exports) {
@@ -19295,6 +19345,7 @@ async function runStdioBridge(port) {
19295
19345
  });
19296
19346
  process.on("SIGINT", () => void bridge.close());
19297
19347
  process.on("SIGTERM", () => void bridge.close());
19348
+ watchAgentGone(() => void bridge.close());
19298
19349
  await bridge.start();
19299
19350
  }
19300
19351
  var BRIDGE_ORIGIN_HEADER, StdioBridge;
@@ -19303,6 +19354,7 @@ var init_StdioBridge = __esm({
19303
19354
  "use strict";
19304
19355
  init_engineUpdating();
19305
19356
  init_stdio2();
19357
+ init_agentGone();
19306
19358
  init_streamableHttp();
19307
19359
  init_AgentToken();
19308
19360
  init_ConfigLoader();
@@ -19906,8 +19958,12 @@ async function main() {
19906
19958
  main();
19907
19959
  `;
19908
19960
  }
19909
- function windowsLauncherSource(nodePath, scriptPath) {
19910
- return `@echo off\\r\\n"${nodePath.replace(/"/g, '""')}" "${scriptPath.replace(/"/g, '""')}"\\r\\n`;
19961
+ function windowsLauncherSource(nodePath, scriptPath, environment) {
19962
+ const setup = Object.entries(environment ?? {}).map(([key, value]) => `set "${key}=${value.replace(/%/g, "%%").replace(/"/g, '""')}"\r
19963
+ `).join("");
19964
+ return `@echo off\r
19965
+ ${setup}"${nodePath.replace(/"/g, '""')}" "${scriptPath.replace(/"/g, '""')}"\r
19966
+ `;
19911
19967
  }
19912
19968
  var path9, LAUNCHER_RESTART_DELAYS_MS;
19913
19969
  var init_launcher = __esm({
@@ -20180,7 +20236,7 @@ function writeGrainCommand(home, platform2 = process.platform, fileSystem = fs9)
20180
20236
  if (platform2 === "win32") {
20181
20237
  const libexec = path12.join(home, "libexec");
20182
20238
  fileSystem.mkdirSync(libexec, { recursive: true });
20183
- const script2 = WIN_SCRIPT.replace("__GRAIN_HOME__", home);
20239
+ const script2 = WIN_SCRIPT.replace("__GRAIN_HOME__", escapePowerShellLiteral(home));
20184
20240
  const psPath = path12.join(libexec, "grain.ps1");
20185
20241
  const psContent = "\uFEFF" + script2 + "\r\n";
20186
20242
  if (!fileSystem.existsSync(psPath) || fileSystem.readFileSync(psPath, "utf8") !== psContent) {
@@ -20205,6 +20261,9 @@ function writeGrainCommand(home, platform2 = process.platform, fileSystem = fs9)
20205
20261
  fileSystem.chmodSync(commandPath, 493);
20206
20262
  }
20207
20263
  }
20264
+ function escapePowerShellLiteral(value) {
20265
+ return value.replace(/'/g, "''");
20266
+ }
20208
20267
  var fs9, path12, POSIX_SCRIPT, WIN_SCRIPT, CMD_SCRIPT;
20209
20268
  var init_grainCommand = __esm({
20210
20269
  "src/server/install/grainCommand.ts"() {
@@ -20229,20 +20288,20 @@ fi
20229
20288
  exec "$node" "$app" "$@"
20230
20289
  `;
20231
20290
  WIN_SCRIPT = `$GrainHome = if ($env:GRAIN_HOME) { $env:GRAIN_HOME } else { '__GRAIN_HOME__' }
20232
- $Node = Get-ChildItem -Path (Join-Path $GrainHome 'runtime\\node') -Directory -ErrorAction SilentlyContinue |
20291
+ $Node = Get-ChildItem -LiteralPath (Join-Path $GrainHome 'runtime\\node') -Directory -ErrorAction SilentlyContinue |
20233
20292
  Sort-Object { try { [version]($_.Name -replace '-.*$', '') } catch { [version]'0.0.0' } }, Name |
20234
20293
  ForEach-Object {
20235
20294
  $FlatNodePath = Join-Path $_.FullName 'Grain.exe'
20236
- if (Test-Path $FlatNodePath) { $FlatNodePath } else { Join-Path $_.FullName 'bin\\Grain.exe' }
20295
+ if (Test-Path -LiteralPath $FlatNodePath) { $FlatNodePath } else { Join-Path $_.FullName 'bin\\Grain.exe' }
20237
20296
  } |
20238
- Where-Object { Test-Path $_ } | Select-Object -Last 1
20239
- $Versions = @(Get-ChildItem -Path (Join-Path $GrainHome 'versions') -Filter '*.json' -ErrorAction SilentlyContinue | ForEach-Object { $_.BaseName }) + @(Get-ChildItem -Path (Join-Path $GrainHome 'app') -Directory -ErrorAction SilentlyContinue | ForEach-Object { $_.Name })
20297
+ Where-Object { Test-Path -LiteralPath $_ } | Select-Object -Last 1
20298
+ $Versions = @(Get-ChildItem -LiteralPath (Join-Path $GrainHome 'versions') -Filter '*.json' -ErrorAction SilentlyContinue | ForEach-Object { $_.BaseName }) + @(Get-ChildItem -LiteralPath (Join-Path $GrainHome 'app') -Directory -ErrorAction SilentlyContinue | ForEach-Object { $_.Name })
20240
20299
  $Version = $Versions |
20241
20300
  Sort-Object { try { [version]($_ -replace '-.*$', '') } catch { [version]'0.0.0' } }, { $_ } |
20242
- Where-Object { Test-Path (Join-Path $GrainHome "app\\$_\\standalone.js") } |
20301
+ Where-Object { Test-Path -LiteralPath (Join-Path $GrainHome "app\\$_\\standalone.js") } |
20243
20302
  Select-Object -Last 1
20244
20303
  $App = if ($Version) { Join-Path $GrainHome "app\\$Version\\standalone.js" } else { $null }
20245
- if (-not $Node -or -not $App -or -not (Test-Path $App)) {
20304
+ if (-not $Node -or -not $App -or -not (Test-Path -LiteralPath $App)) {
20246
20305
  [Console]::Error.WriteLine("Grain is not installed correctly in $GrainHome. Reinstall with: irm https://grain.tools/install.ps1 | iex")
20247
20306
  exit 1
20248
20307
  }
@@ -21838,7 +21897,7 @@ var require_package = __commonJS({
21838
21897
  name: "grain",
21839
21898
  displayName: "Grain SQL",
21840
21899
  description: "Run SQL in VS Code and expose safe, visible MCP database tools for Claude, Cursor, and other AI agents.",
21841
- version: "0.10.21",
21900
+ version: "0.10.22",
21842
21901
  license: "UNLICENSED",
21843
21902
  mcpName: "io.github.pattrnlabs/grain",
21844
21903
  publisher: "pattrnlabs",
@@ -22514,6 +22573,7 @@ var require_package = __commonJS({
22514
22573
  "pretest:medium:webapp-gate": "npm run build:web-app",
22515
22574
  "test:medium:webapp-gate": "vitest run --config vitest.medium.config.ts src/test/medium/standaloneWebAppGate.medium.test.js",
22516
22575
  "test:integration:stdio-bridge": 'node scripts/emit-seam-receipt.js "npm run test:integration:stdio-bridge" -- vitest run --no-file-parallelism src/test/integration/stdio_bridge.test.ts',
22576
+ "test:seam:trino-axios": 'node scripts/emit-seam-receipt.js "npm run test:seam:trino-axios" -- vitest run --config packages/sql-preview-trino/vitest.config.ts packages/sql-preview-trino/src/__tests__/TrinoConnector.axios-seam.test.ts',
22517
22577
  "test:medium:rfc-baseline": "vitest run --config vitest.medium.config.ts src/test/medium/rfcBaselineResolution.medium.test.js",
22518
22578
  "test:integration": "node ./out/test/runTest.js",
22519
22579
  prewalkthrough: "npm run compile && node scripts/build-daemon.js --entry=standalone",
@@ -22748,7 +22808,7 @@ function postJson(url3, payload, timeoutMs) {
22748
22808
  const parsed = new import_url.URL(url3);
22749
22809
  const body = JSON.stringify(payload);
22750
22810
  const client = parsed.protocol === "http:" ? http3 : https;
22751
- const request3 = client.request(
22811
+ const request4 = client.request(
22752
22812
  {
22753
22813
  hostname: parsed.hostname,
22754
22814
  method: "POST",
@@ -22778,10 +22838,10 @@ function postJson(url3, payload, timeoutMs) {
22778
22838
  });
22779
22839
  }
22780
22840
  );
22781
- request3.on("timeout", () => request3.destroy(new Error("Telemetry request timed out")));
22782
- request3.on("error", reject);
22783
- request3.write(body);
22784
- request3.end();
22841
+ request4.on("timeout", () => request4.destroy(new Error("Telemetry request timed out")));
22842
+ request4.on("error", reject);
22843
+ request4.write(body);
22844
+ request4.end();
22785
22845
  });
22786
22846
  }
22787
22847
  var http3, https, import_url, DEFAULT_POSTHOG_HOST, TelemetrySendError, TelemetryEmitter, DEFAULT_TELEMETRY_TRANSPORT;
@@ -23307,11 +23367,11 @@ function downloadToFile(url3, destPath, options) {
23307
23367
  const download = (currentUrl, redirects) => {
23308
23368
  try {
23309
23369
  const client = clientFor(currentUrl);
23310
- const request3 = client.get(currentUrl, (response) => {
23370
+ const request4 = client.get(currentUrl, (response) => {
23311
23371
  clearHopTimers();
23312
23372
  if ([301, 302, 303, 307, 308].includes(response.statusCode ?? 0)) {
23313
23373
  response.destroy();
23314
- request3.destroy();
23374
+ request4.destroy();
23315
23375
  if (redirects >= 5) {
23316
23376
  failOnce(new Error(`Download failed for ${url3}: too many redirects`));
23317
23377
  return;
@@ -23349,7 +23409,7 @@ function downloadToFile(url3, destPath, options) {
23349
23409
  clearTimeout(idleTimeout);
23350
23410
  }
23351
23411
  idleTimeout = setTimeout(() => {
23352
- request3.destroy();
23412
+ request4.destroy();
23353
23413
  failOnce(new Error(`Download timed out waiting for data for ${currentUrl}`));
23354
23414
  }, idleTimeoutMs);
23355
23415
  };
@@ -23358,7 +23418,7 @@ function downloadToFile(url3, destPath, options) {
23358
23418
  receivedBytes += chunk.length;
23359
23419
  if (options?.maxBytes !== void 0 && receivedBytes > options.maxBytes) {
23360
23420
  failOnce(new Error("Download exceeded expected size"));
23361
- request3.destroy();
23421
+ request4.destroy();
23362
23422
  }
23363
23423
  });
23364
23424
  resetIdleTimeout();
@@ -23377,12 +23437,12 @@ function downloadToFile(url3, destPath, options) {
23377
23437
  });
23378
23438
  file5.on("error", failOnce);
23379
23439
  });
23380
- activeRequest = request3;
23440
+ activeRequest = request4;
23381
23441
  responseTimeout = setTimeout(() => {
23382
- request3.destroy();
23442
+ request4.destroy();
23383
23443
  failOnce(new Error(`Download timed out waiting for response headers for ${currentUrl}`));
23384
23444
  }, responseTimeoutMs);
23385
- request3.on("error", failOnce);
23445
+ request4.on("error", failOnce);
23386
23446
  } catch (error52) {
23387
23447
  failOnce(error52 instanceof Error ? error52 : new Error(String(error52)));
23388
23448
  }
@@ -24099,6 +24159,11 @@ var init_supervisorUnits = __esm({
24099
24159
  // src/server/install/launchAgent.ts
24100
24160
  function generateLaunchAgent(descriptor) {
24101
24161
  const dest = serviceUnitRelativePath("darwin", descriptor.serviceIdentifier);
24162
+ const environment = { GRAIN_HOME: descriptor.configHome, ...descriptor.environment };
24163
+ const environmentEntries = Object.entries(environment).map(
24164
+ ([name, value]) => ` <key>${escapeXml(name)}</key>
24165
+ <string>${escapeXml(value)}</string>`
24166
+ ).join("\n");
24102
24167
  const content = `<?xml version="1.0" encoding="UTF-8"?>
24103
24168
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
24104
24169
  <plist version="1.0">
@@ -24112,8 +24177,7 @@ function generateLaunchAgent(descriptor) {
24112
24177
  </array>
24113
24178
  <key>EnvironmentVariables</key>
24114
24179
  <dict>
24115
- <key>GRAIN_HOME</key>
24116
- <string>${escapeXml(descriptor.configHome)}</string>
24180
+ ${environmentEntries}
24117
24181
  </dict>
24118
24182
  <key>StandardOutPath</key>
24119
24183
  <string>${escapeXml(descriptor.stdoutPath)}</string>
@@ -24159,13 +24223,15 @@ function generateSystemdUserUnit(descriptor) {
24159
24223
  }
24160
24224
  return str;
24161
24225
  };
24226
+ const environment = { GRAIN_HOME: descriptor.configHome, ...descriptor.environment };
24227
+ const environmentEntries = Object.entries(environment).map(([name, value]) => `Environment=${name}=${escapeExec(value)}`).join("\n");
24162
24228
  const content = `[Unit]
24163
24229
  Description=${descriptor.serviceIdentifier} Supervisor
24164
24230
  After=network.target
24165
24231
 
24166
24232
  [Service]
24167
24233
  ExecStart=${escapeExec(descriptor.nodePath)} ${escapeExec(descriptor.launcherPath)}
24168
- Environment=GRAIN_HOME=${escapeExec(descriptor.configHome)}
24234
+ ${environmentEntries}
24169
24235
  StandardOutput=append:${descriptor.stdoutPath}
24170
24236
  StandardError=append:${descriptor.stderrPath}
24171
24237
  Restart=always
@@ -24743,7 +24809,7 @@ function writeAtomicPointer(fileSystem, pointerPath2, contents, mode) {
24743
24809
  throw error52;
24744
24810
  }
24745
24811
  }
24746
- function writeLauncherAtomically(fileSystem, platform2, configHome, nodePath) {
24812
+ function writeLauncherAtomically(fileSystem, platform2, configHome, nodePath, environment) {
24747
24813
  const scriptPath = launcherPath(configHome);
24748
24814
  writeAtomicPointer(fileSystem, scriptPath, launcherSource(configHome), 448);
24749
24815
  fileSystem.chmodSync(scriptPath, 448);
@@ -24751,7 +24817,7 @@ function writeLauncherAtomically(fileSystem, platform2, configHome, nodePath) {
24751
24817
  writeAtomicPointer(
24752
24818
  fileSystem,
24753
24819
  platformLauncherPath(platform2, configHome),
24754
- windowsLauncherSource(nodePath, scriptPath)
24820
+ windowsLauncherSource(nodePath, scriptPath, environment)
24755
24821
  );
24756
24822
  }
24757
24823
  }
@@ -24816,22 +24882,30 @@ var init_serviceReadiness = __esm({
24816
24882
  });
24817
24883
 
24818
24884
  // src/server/install/installCommand.ts
24819
- function unitFor(platform2, launcher, configHome, nodePath) {
24885
+ function unitFor(platform2, launcher, configHome, nodePath, env2 = {}) {
24886
+ const environment = env2["GRAIN_TEST_FORBID_NATIVE_KEYCHAIN"] === "1" ? Object.fromEntries(
24887
+ [
24888
+ "GRAIN_TEST_FORBID_NATIVE_KEYCHAIN",
24889
+ "GRAIN_TEST_KEYRING_MODULE_PATH",
24890
+ "GRAIN_TEST_KEYRING_STORE_PATH"
24891
+ ].filter((name) => env2[name] !== void 0).map((name) => [name, env2[name]])
24892
+ ) : void 0;
24820
24893
  const descriptor = {
24821
24894
  launcherPath: launcher,
24822
24895
  nodePath,
24823
24896
  configHome,
24824
24897
  serviceIdentifier: GRAIN_SERVICE_LABEL,
24825
24898
  stdoutPath: path27.join(configHome, "grain-daemon.out.log"),
24826
- stderrPath: path27.join(configHome, "grain-daemon.err.log")
24899
+ stderrPath: path27.join(configHome, "grain-daemon.err.log"),
24900
+ ...environment ? { environment } : {}
24827
24901
  };
24828
24902
  if (platform2 === "darwin") {
24829
- return generateLaunchAgent(descriptor);
24903
+ return { ...generateLaunchAgent(descriptor), ...environment ? { environment } : {} };
24830
24904
  }
24831
24905
  if (platform2 === "linux") {
24832
- return generateSystemdUserUnit(descriptor);
24906
+ return { ...generateSystemdUserUnit(descriptor), ...environment ? { environment } : {} };
24833
24907
  }
24834
- return generateWindowsStartupTask(descriptor);
24908
+ return { ...generateWindowsStartupTask(descriptor), ...environment ? { environment } : {} };
24835
24909
  }
24836
24910
  function platformLauncherPath2(platform2, configHome) {
24837
24911
  return platform2 === "win32" ? path27.join(configHome, "grain-daemon-launcher.cmd") : launcherPath(configHome);
@@ -24987,13 +25061,13 @@ async function installCommand(deps = {}) {
24987
25061
  throw error52;
24988
25062
  });
24989
25063
  const launcher = platformLauncherPath2(platform2, configHome);
24990
- const unit = unitFor(platform2, launcher, configHome, nodePath);
25064
+ const unit = unitFor(platform2, launcher, configHome, nodePath, process.env);
24991
25065
  const unitPath = path27.join(homeDirectory, unit.destination);
24992
25066
  const initialStatus = await readStatus();
24993
25067
  const unitExists = fileSystem.existsSync(unitPath);
24994
25068
  const unitChanged = !unitExists || String(fileSystem.readFileSync(unitPath, { encoding: unit.encoding })) !== unit.content;
24995
25069
  const registered = await adapter2.isRegistered(GRAIN_SERVICE_LABEL);
24996
- writeLauncherAtomically(fileSystem, platform2, configHome, nodePath);
25070
+ writeLauncherAtomically(fileSystem, platform2, configHome, nodePath, unit.environment);
24997
25071
  const installedVersion = deps.installedVersion ?? readDaemonVersion();
24998
25072
  if (!installedVersion) {
24999
25073
  const errLog2 = path27.join(configHome, "grain-daemon.err.log");
@@ -27093,6 +27167,81 @@ var init_spawnOnDemandStart = __esm({
27093
27167
  }
27094
27168
  });
27095
27169
 
27170
+ // src/server/cli/stopCommand.ts
27171
+ var stopCommand_exports = {};
27172
+ __export(stopCommand_exports, {
27173
+ stopCommand: () => stopCommand
27174
+ });
27175
+ function defaultIsProcessAlive(pid) {
27176
+ try {
27177
+ process.kill(pid, 0);
27178
+ return true;
27179
+ } catch (error52) {
27180
+ return error52.code !== "ESRCH";
27181
+ }
27182
+ }
27183
+ async function stopCommand(configDir = resolveGrainHome(), clock = Date, processKiller = process.kill, adapter2 = createSupervisorAdapter(
27184
+ process.platform,
27185
+ createCommandRunner(),
27186
+ process.getuid?.() ?? 0
27187
+ ), isProcessAlive = defaultIsProcessAlive, platform2 = process.platform, requestStop = requestDaemonControlStop) {
27188
+ if (await adapter2.isRegistered(DAEMON_SERVICE_IDENTITY)) {
27189
+ console.error(
27190
+ "Grain is installed as a background service. Run `grain uninstall` to remove it."
27191
+ );
27192
+ return 1;
27193
+ }
27194
+ const status = await readGrainServiceStatus(configDir);
27195
+ if (!isRunningGrainService(status)) {
27196
+ console.log("Grain is not running.");
27197
+ return 0;
27198
+ }
27199
+ const pid = readDaemonEndpoint(configDir)?.pid;
27200
+ if (pid === void 0) {
27201
+ console.error("Could not determine Grain daemon PID.");
27202
+ return 1;
27203
+ }
27204
+ const token = platform2 === "win32" ? readDaemonAuthToken(configDir) : void 0;
27205
+ const accepted = token ? await requestStop(daemonControlEndpoint(configDir), token) : false;
27206
+ try {
27207
+ if (!accepted) {
27208
+ processKiller(pid, "SIGTERM");
27209
+ }
27210
+ } catch (error52) {
27211
+ const code = error52.code;
27212
+ if (code !== "ESRCH") {
27213
+ console.error(`Could not signal Grain (pid ${pid}): ${code ?? String(error52)}`);
27214
+ return 1;
27215
+ }
27216
+ }
27217
+ const startMs = clock.now();
27218
+ const timeoutMs = accepted ? drainStopBudgetMs(configDir) : 1e4;
27219
+ while (clock.now() - startMs < timeoutMs) {
27220
+ const currentStatus = await readGrainServiceStatus(configDir);
27221
+ if (!isRunningGrainService(currentStatus) && !isProcessAlive(pid)) {
27222
+ console.log("Grain stopped.");
27223
+ return 0;
27224
+ }
27225
+ await new Promise((resolve15) => setTimeout(resolve15, 250));
27226
+ }
27227
+ console.error(`Grain did not stop within ${timeoutMs / 1e3} seconds.`);
27228
+ return 1;
27229
+ }
27230
+ var init_stopCommand = __esm({
27231
+ "src/server/cli/stopCommand.ts"() {
27232
+ "use strict";
27233
+ init_grainHome();
27234
+ init_daemonEndpointFile();
27235
+ init_statusCommand();
27236
+ init_supervisorAdapter();
27237
+ init_daemonRecordInstance();
27238
+ init_ipcEndpoint();
27239
+ init_DaemonAuthToken();
27240
+ init_requestDaemonControlStop();
27241
+ init_drainStopBudget();
27242
+ }
27243
+ });
27244
+
27096
27245
  // src/server/cli/serviceControl.ts
27097
27246
  var serviceControl_exports = {};
27098
27247
  __export(serviceControl_exports, {
@@ -27107,29 +27256,150 @@ function printSuccess(version3, status) {
27107
27256
  process.stdout.write(`Grain ${version3} is running at ${url3}.
27108
27257
  `);
27109
27258
  }
27110
- async function serviceManagesHome(options) {
27111
- if (!await options.adapter.isRegistered(GRAIN_SERVICE_LABEL)) {
27112
- return false;
27259
+ async function inspectServiceHomeOwnership(options) {
27260
+ try {
27261
+ if (!await options.adapter.isRegistered(GRAIN_SERVICE_LABEL)) {
27262
+ return "unregistered";
27263
+ }
27264
+ } catch {
27265
+ return "unknown";
27113
27266
  }
27114
27267
  const platform2 = options.platform ?? process.platform;
27115
27268
  const launcher = platformLauncherPath2(platform2, options.configHome);
27116
- const unit = unitFor(platform2, launcher, options.configHome, process.execPath);
27269
+ const unit = unitFor(platform2, launcher, options.configHome, process.execPath, process.env);
27117
27270
  const unitPath = (0, import_path5.join)(options.homeDirectory ?? (0, import_os.homedir)(), unit.destination);
27118
- const content = (options.readUnit ?? defaultReadUnit)(unitPath, unit.encoding);
27119
- if (content === void 0) {
27120
- return false;
27271
+ let content;
27272
+ try {
27273
+ content = (options.readUnit ?? defaultReadUnit)(unitPath, unit.encoding);
27274
+ } catch {
27275
+ return "unknown";
27121
27276
  }
27122
- return content.includes(launcher) || content.includes(escapeXml(launcher));
27277
+ if (!content?.trim()) {
27278
+ return "unknown";
27279
+ }
27280
+ const registeredLauncher = parseRecognizedGrainLauncher(platform2, content);
27281
+ if (!registeredLauncher) {
27282
+ return "unknown";
27283
+ }
27284
+ return registeredLauncher === launcher ? "this-home" : "other-home";
27285
+ }
27286
+ function parseRecognizedGrainLauncher(platform2, content) {
27287
+ const fields = platform2 === "darwin" ? parseLaunchAgent(content) : platform2 === "linux" ? parseSystemdUnit(content) : parseWindowsTask(content);
27288
+ if (!fields) {
27289
+ return void 0;
27290
+ }
27291
+ if (fields.launcher !== platformLauncherPath2(platform2, fields.configHome)) {
27292
+ return void 0;
27293
+ }
27294
+ const expected = unitFor(
27295
+ platform2,
27296
+ fields.launcher,
27297
+ fields.configHome,
27298
+ fields.nodePath ?? process.execPath,
27299
+ process.env
27300
+ ).content;
27301
+ return content === expected ? fields.launcher : void 0;
27302
+ }
27303
+ function decodeXmlText(value) {
27304
+ const decoded = value.replace(/&(amp|lt|gt|quot|apos);/g, (_entity, name) => {
27305
+ switch (name) {
27306
+ case "amp":
27307
+ return "&";
27308
+ case "lt":
27309
+ return "<";
27310
+ case "gt":
27311
+ return ">";
27312
+ case "quot":
27313
+ return '"';
27314
+ default:
27315
+ return "'";
27316
+ }
27317
+ });
27318
+ return escapeXml(decoded) === value ? decoded : void 0;
27319
+ }
27320
+ function parseXmlStringAfter(content, marker) {
27321
+ const markerIndex = content.indexOf(marker);
27322
+ const match = markerIndex < 0 ? void 0 : /^\s*<string>([^<]*)<\/string>/.exec(content.slice(markerIndex + marker.length));
27323
+ const value = match?.[1];
27324
+ return value === void 0 ? void 0 : decodeXmlText(value);
27325
+ }
27326
+ function parseLaunchAgent(content) {
27327
+ const args = /<key>ProgramArguments<\/key>\s*<array>\s*<string>([^<]*)<\/string>\s*<string>([^<]*)<\/string>\s*<\/array>/.exec(
27328
+ content
27329
+ );
27330
+ const nodeValue = args?.[1];
27331
+ const launcherValue = args?.[2];
27332
+ const nodePath = nodeValue === void 0 ? void 0 : decodeXmlText(nodeValue);
27333
+ const launcher = launcherValue === void 0 ? void 0 : decodeXmlText(launcherValue);
27334
+ const configHome = parseXmlStringAfter(content, "<key>GRAIN_HOME</key>");
27335
+ return nodePath && launcher && configHome ? { nodePath, launcher, configHome } : void 0;
27336
+ }
27337
+ function parseSystemdArgument(value) {
27338
+ if (value.startsWith('"') && value.endsWith('"')) {
27339
+ const unescaped = value.slice(1, -1).replace(/\\(["\\])/g, "$1");
27340
+ return `"${unescaped.replace(/(["\\])/g, "\\$1")}"` === value ? unescaped : void 0;
27341
+ }
27342
+ return /[\s"&]/.test(value) ? void 0 : value;
27343
+ }
27344
+ function parseSystemdUnit(content) {
27345
+ const execStart = /^ExecStart=(\S+|"(?:\\.|[^"\\])*"?) (\S+|"(?:\\.|[^"\\])*"?)$/m.exec(content);
27346
+ const environment = /^Environment=GRAIN_HOME=(\S+|"(?:\\.|[^"\\])*"?)$/m.exec(content);
27347
+ const nodeValue = execStart?.[1];
27348
+ const launcherValue = execStart?.[2];
27349
+ const homeValue = environment?.[1];
27350
+ const nodePath = nodeValue === void 0 ? void 0 : parseSystemdArgument(nodeValue);
27351
+ const launcher = launcherValue === void 0 ? void 0 : parseSystemdArgument(launcherValue);
27352
+ const configHome = homeValue === void 0 ? void 0 : parseSystemdArgument(homeValue);
27353
+ return nodePath && launcher && configHome ? { nodePath, launcher, configHome } : void 0;
27354
+ }
27355
+ function parseWindowsTask(content) {
27356
+ const command = /<Command>([^<]*)<\/Command>/.exec(content);
27357
+ const commandValue = command?.[1];
27358
+ const launcher = commandValue === void 0 ? void 0 : decodeXmlText(commandValue);
27359
+ return launcher ? { launcher, configHome: (0, import_path5.dirname)(launcher) } : void 0;
27360
+ }
27361
+ async function serviceManagesHome(options) {
27362
+ return await inspectServiceHomeOwnership(options) === "this-home";
27123
27363
  }
27124
27364
  async function requireForegroundAllowed(supervised, adapter2, configHome = resolveGrainHome(), readUnit) {
27125
- if (supervised)
27365
+ if (supervised) {
27126
27366
  return;
27127
- if (await serviceManagesHome({ adapter: adapter2, configHome, ...readUnit ? { readUnit } : {} })) {
27367
+ }
27368
+ const ownership = await inspectServiceHomeOwnership({
27369
+ adapter: adapter2,
27370
+ configHome,
27371
+ ...readUnit ? { readUnit } : {}
27372
+ });
27373
+ if (ownership === "this-home") {
27128
27374
  throw new Error(
27129
27375
  `Grain's background service is installed, so Grain is already managed by it. Use grain restart, or grain uninstall first to run it in the foreground.
27130
27376
  `
27131
27377
  );
27132
27378
  }
27379
+ if (ownership === "unknown") {
27380
+ throw new Error(
27381
+ "Grain's background service is registered, but its definition could not be safely read; refusing to run in the foreground.\n"
27382
+ );
27383
+ }
27384
+ }
27385
+ async function restartOnDemandHome(configHome, adapter2, readUnit) {
27386
+ const ownership = await inspectServiceHomeOwnership({
27387
+ adapter: adapter2,
27388
+ configHome,
27389
+ ...readUnit ? { readUnit } : {}
27390
+ });
27391
+ if (ownership === "this-home" || ownership === "unknown") {
27392
+ process.stderr.write(
27393
+ "Grain service ownership could not be safely established for this home; refusing direct restart.\n"
27394
+ );
27395
+ return 1;
27396
+ }
27397
+ const stopAdapter = ownership === "other-home" ? { ...adapter2, isRegistered: async () => false } : adapter2;
27398
+ const stopExitCode = await stopCommand(configHome, void 0, void 0, stopAdapter);
27399
+ if (stopExitCode !== 0) {
27400
+ return stopExitCode;
27401
+ }
27402
+ return await spawnOnDemandStart(configHome);
27133
27403
  }
27134
27404
  async function startThroughService(options) {
27135
27405
  const adapter2 = options.adapter ?? createSupervisorAdapter(
@@ -27139,17 +27409,38 @@ async function startThroughService(options) {
27139
27409
  options.configHome
27140
27410
  );
27141
27411
  const install56 = options.install ?? (() => installCommand({ configHome: options.configHome }));
27412
+ const installAndStartFallback = async () => {
27413
+ const exitCode = await install56();
27414
+ if (exitCode !== 0) {
27415
+ return exitCode;
27416
+ }
27417
+ const installedServiceMode = readServiceModeStatus(options.configHome);
27418
+ if (installedServiceMode.type === "valid" && installedServiceMode.record.mode === "spawn-on-demand") {
27419
+ return await spawnOnDemandStart(options.configHome);
27420
+ }
27421
+ return exitCode;
27422
+ };
27142
27423
  const serviceMode = readServiceModeStatus(options.configHome);
27143
27424
  if (serviceMode.type === "valid" && serviceMode.record.mode === "spawn-on-demand") {
27425
+ if (options.restart) {
27426
+ return await restartOnDemandHome(options.configHome, adapter2, options.readUnit);
27427
+ }
27144
27428
  return await spawnOnDemandStart(options.configHome);
27145
27429
  }
27146
- const manages = await serviceManagesHome({
27430
+ const ownership = await inspectServiceHomeOwnership({
27147
27431
  adapter: adapter2,
27148
27432
  configHome: options.configHome,
27149
27433
  ...options.readUnit ? { readUnit: options.readUnit } : {}
27150
27434
  });
27435
+ if (options.restart && ownership === "unknown") {
27436
+ process.stderr.write(
27437
+ "Grain service ownership could not be safely established for this home; refusing restart.\n"
27438
+ );
27439
+ return 1;
27440
+ }
27441
+ const manages = ownership === "this-home";
27151
27442
  if (!manages) {
27152
- return await install56();
27443
+ return await installAndStartFallback();
27153
27444
  }
27154
27445
  const activeJsonPath = (0, import_path5.join)(options.configHome, ACTIVE_VERSION_FILENAME);
27155
27446
  let activeJson = {};
@@ -27159,7 +27450,7 @@ async function startThroughService(options) {
27159
27450
  }
27160
27451
  const expectedVersion = activeJson.version;
27161
27452
  if (!expectedVersion) {
27162
- return await install56();
27453
+ return await installAndStartFallback();
27163
27454
  }
27164
27455
  const readStatus = options.readStatus ?? (() => readGrainServiceStatus(options.configHome));
27165
27456
  const waitFn = options.wait ?? (() => waitForVersion(readStatus, (ms) => new Promise((r) => setTimeout(r, ms)), expectedVersion));
@@ -27226,6 +27517,7 @@ var init_serviceControl = __esm({
27226
27517
  init_launchFailureMarker();
27227
27518
  init_serviceMode();
27228
27519
  init_spawnOnDemandStart();
27520
+ init_stopCommand();
27229
27521
  defaultReadUnit = (unitPath, encoding) => {
27230
27522
  try {
27231
27523
  return fs28.readFileSync(unitPath, { encoding });
@@ -27324,7 +27616,8 @@ var init_localBrowserPaths = __esm({
27324
27616
  // src/server/install/supervisedStart.ts
27325
27617
  function readCgroup() {
27326
27618
  try {
27327
- return fs29.readFileSync("/proc/self/cgroup", "utf8");
27619
+ const cgroup = fs29.readFileSync("/proc/self/cgroup", "utf8");
27620
+ return typeof cgroup === "string" ? cgroup : "";
27328
27621
  } catch {
27329
27622
  return "";
27330
27623
  }
@@ -27396,6 +27689,162 @@ var init_supervisedStart = __esm({
27396
27689
  }
27397
27690
  });
27398
27691
 
27692
+ // src/services/featureFlags/FeatureFlagDefinitions.ts
27693
+ var FEATURE_FLAGS;
27694
+ var init_FeatureFlagDefinitions = __esm({
27695
+ "src/services/featureFlags/FeatureFlagDefinitions.ts"() {
27696
+ "use strict";
27697
+ FEATURE_FLAGS = {
27698
+ managedDuckDbRuntime: {
27699
+ id: "sql_preview_managed_duckdb_runtime",
27700
+ defaultValue: true,
27701
+ description: "Gates background auto-provisioning of the managed DuckDB runtime (RFC-075).",
27702
+ source: "local"
27703
+ },
27704
+ standaloneWebApp: {
27705
+ id: "sql_preview_standalone_web_app",
27706
+ defaultValue: true,
27707
+ description: "Gates the local workbench serving route (RFC-163), opened with `grain ui`.",
27708
+ source: "local"
27709
+ },
27710
+ charts: {
27711
+ id: "sql_preview_charts",
27712
+ defaultValue: false,
27713
+ description: "Gates the chart representation UI and MCP chart tools (RFC-070).",
27714
+ source: "posthog"
27715
+ },
27716
+ sessionReplay: {
27717
+ id: "sql_preview_session_replay",
27718
+ defaultValue: false,
27719
+ description: "Gates masked PostHog session replay in VS Code webviews (RFC-069).",
27720
+ source: "posthog"
27721
+ },
27722
+ executionLedger: {
27723
+ id: "sql_preview_execution_ledger",
27724
+ defaultValue: false,
27725
+ description: "Gates local execution-ledger journaling and provenance capture (RFC-071).",
27726
+ source: "posthog"
27727
+ },
27728
+ credentialRequiredSignal: {
27729
+ id: "sql_preview_credential_required_signal",
27730
+ defaultValue: true,
27731
+ description: "Offers a one-time credential page on auth-failed queries (RFC-171).",
27732
+ source: "local",
27733
+ locked: true
27734
+ },
27735
+ crashDiagnostics: {
27736
+ id: "sql_preview_crash_diagnostics",
27737
+ defaultValue: true,
27738
+ description: "Gates posthog-node exception autocapture on the daemon (RFC-092).",
27739
+ source: "local"
27740
+ },
27741
+ mcpSurface: {
27742
+ id: "sql_preview_mcp_surface",
27743
+ defaultValue: false,
27744
+ description: "Gates the generic MCP HTTP surface, requiring both entitlement and local consent (RFC-110).",
27745
+ source: "posthog"
27746
+ },
27747
+ resultsCardRouting: {
27748
+ id: "results-card-routing",
27749
+ defaultValue: true,
27750
+ description: "Gates two-view MCP result routing (RFC-167).",
27751
+ source: "posthog"
27752
+ }
27753
+ };
27754
+ }
27755
+ });
27756
+
27757
+ // src/services/featureFlags/isFeatureEnabled.ts
27758
+ function isFeatureEnabled(key, env2 = process.env) {
27759
+ const definition = FEATURE_FLAGS[key];
27760
+ if (definition.locked) {
27761
+ return definition.defaultValue;
27762
+ }
27763
+ const override = env2[`GRAIN_FF_${definition.id.toUpperCase()}`];
27764
+ if (override === "1" || override === "true") {
27765
+ return true;
27766
+ }
27767
+ if (override === "0" || override === "false") {
27768
+ return false;
27769
+ }
27770
+ return definition.defaultValue;
27771
+ }
27772
+ var init_isFeatureEnabled = __esm({
27773
+ "src/services/featureFlags/isFeatureEnabled.ts"() {
27774
+ "use strict";
27775
+ init_FeatureFlagDefinitions();
27776
+ }
27777
+ });
27778
+
27779
+ // src/server/policy/callPolicy.ts
27780
+ function clientPolicyFromMeta(meta3) {
27781
+ const asked = meta3?.[CLIENT_POLICY_META_KEY];
27782
+ if (typeof asked !== "object" || asked === null)
27783
+ return void 0;
27784
+ const safeMode = asked.safeMode;
27785
+ return typeof safeMode === "boolean" ? { safeMode } : {};
27786
+ }
27787
+ function resolveCallPolicy(serviceProfile, serviceSafeMode, requested) {
27788
+ if (requested?.safeMode === void 0) {
27789
+ return { profile: serviceProfile, declined: [] };
27790
+ }
27791
+ if (requested.safeMode) {
27792
+ const tightened = { ...serviceProfile, forceSafeMode: true };
27793
+ return { profile: composeToolProfiles(serviceProfile, tightened), declined: [] };
27794
+ }
27795
+ if (isSafeModeActive(serviceProfile, serviceSafeMode)) {
27796
+ return { profile: serviceProfile, declined: [SAFE_MODE_DECLINED_MESSAGE] };
27797
+ }
27798
+ return { profile: serviceProfile, declined: [] };
27799
+ }
27800
+ function alphaToolEnabled(name, chartsEnabled = isFeatureEnabled("charts"), ledgerEnabled = isFeatureEnabled("executionLedger")) {
27801
+ if (CHART_TOOLS.includes(name))
27802
+ return chartsEnabled;
27803
+ if (LEDGER_TOOLS.includes(name))
27804
+ return ledgerEnabled;
27805
+ return true;
27806
+ }
27807
+ function admitToolCall(profile, name, featureEnabled) {
27808
+ if (!toolNamesForProfile(profile).has(name) || !featureEnabled) {
27809
+ throw new Error("Unknown tool");
27810
+ }
27811
+ return refuseIfNotPermitted(profile, name);
27812
+ }
27813
+ function refuseRestToolCall(profile, name) {
27814
+ const tool = name;
27815
+ if (!ALL_TOOLS.includes(tool)) {
27816
+ return void 0;
27817
+ }
27818
+ if (!toolNamesForProfile(profile).has(name)) {
27819
+ return toolRefusalResult(profile, tool);
27820
+ }
27821
+ return refuseIfNotPermitted(profile, name);
27822
+ }
27823
+ function withPolicyNotice(result, policy) {
27824
+ if (policy.declined.length === 0)
27825
+ return result;
27826
+ const existing = result;
27827
+ const notice = { type: "text", text: policy.declined.join(" ") };
27828
+ return {
27829
+ ...existing,
27830
+ content: Array.isArray(existing.content) ? [...existing.content, notice] : [notice],
27831
+ _meta: { ...existing._meta, [DECLINED_POLICY_META_KEY]: policy.declined }
27832
+ };
27833
+ }
27834
+ var CLIENT_POLICY_META_KEY, DECLINED_POLICY_META_KEY, SAFE_MODE_DECLINED_MESSAGE, CHART_TOOLS, LEDGER_TOOLS;
27835
+ var init_callPolicy = __esm({
27836
+ "src/server/policy/callPolicy.ts"() {
27837
+ "use strict";
27838
+ init_isFeatureEnabled();
27839
+ init_toolProfiles();
27840
+ CLIENT_POLICY_META_KEY = "sqlpreview/policy";
27841
+ DECLINED_POLICY_META_KEY = "sqlpreview/policyDeclined";
27842
+ SAFE_MODE_DECLINED_MESSAGE = "Declined this client's request to run with safe mode off: 'mcpSafeMode' is client-restrict-only, so an attaching client may only make it more restrictive than the service, never less. This call ran under safe mode; the override was declined, not lost.";
27843
+ CHART_TOOLS = ["render_chart", "save_chart", "list_charts"];
27844
+ LEDGER_TOOLS = ["ledger_stats", "verify_ledger"];
27845
+ }
27846
+ });
27847
+
27399
27848
  // node_modules/zod/v4/mini/parse.js
27400
27849
  var init_parse3 = __esm({
27401
27850
  "node_modules/zod/v4/mini/parse.js"() {
@@ -27956,8 +28405,8 @@ var init_protocol = __esm({
27956
28405
  this._taskStore = _options?.taskStore;
27957
28406
  this._taskMessageQueue = _options?.taskMessageQueue;
27958
28407
  if (this._taskStore) {
27959
- this.setRequestHandler(GetTaskRequestSchema, async (request3, extra) => {
27960
- const task = await this._taskStore.getTask(request3.params.taskId, extra.sessionId);
28408
+ this.setRequestHandler(GetTaskRequestSchema, async (request4, extra) => {
28409
+ const task = await this._taskStore.getTask(request4.params.taskId, extra.sessionId);
27961
28410
  if (!task) {
27962
28411
  throw new McpError(ErrorCode.InvalidParams, "Failed to retrieve task: Task not found");
27963
28412
  }
@@ -27965,9 +28414,9 @@ var init_protocol = __esm({
27965
28414
  ...task
27966
28415
  };
27967
28416
  });
27968
- this.setRequestHandler(GetTaskPayloadRequestSchema, async (request3, extra) => {
28417
+ this.setRequestHandler(GetTaskPayloadRequestSchema, async (request4, extra) => {
27969
28418
  const handleTaskResult = async () => {
27970
- const taskId = request3.params.taskId;
28419
+ const taskId = request4.params.taskId;
27971
28420
  if (this._taskMessageQueue) {
27972
28421
  let queuedMessage;
27973
28422
  while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
@@ -28018,9 +28467,9 @@ var init_protocol = __esm({
28018
28467
  };
28019
28468
  return await handleTaskResult();
28020
28469
  });
28021
- this.setRequestHandler(ListTasksRequestSchema, async (request3, extra) => {
28470
+ this.setRequestHandler(ListTasksRequestSchema, async (request4, extra) => {
28022
28471
  try {
28023
- const { tasks, nextCursor } = await this._taskStore.listTasks(request3.params?.cursor, extra.sessionId);
28472
+ const { tasks, nextCursor } = await this._taskStore.listTasks(request4.params?.cursor, extra.sessionId);
28024
28473
  return {
28025
28474
  tasks,
28026
28475
  nextCursor,
@@ -28030,20 +28479,20 @@ var init_protocol = __esm({
28030
28479
  throw new McpError(ErrorCode.InvalidParams, `Failed to list tasks: ${error52 instanceof Error ? error52.message : String(error52)}`);
28031
28480
  }
28032
28481
  });
28033
- this.setRequestHandler(CancelTaskRequestSchema, async (request3, extra) => {
28482
+ this.setRequestHandler(CancelTaskRequestSchema, async (request4, extra) => {
28034
28483
  try {
28035
- const task = await this._taskStore.getTask(request3.params.taskId, extra.sessionId);
28484
+ const task = await this._taskStore.getTask(request4.params.taskId, extra.sessionId);
28036
28485
  if (!task) {
28037
- throw new McpError(ErrorCode.InvalidParams, `Task not found: ${request3.params.taskId}`);
28486
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${request4.params.taskId}`);
28038
28487
  }
28039
28488
  if (isTerminal(task.status)) {
28040
28489
  throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
28041
28490
  }
28042
- await this._taskStore.updateTaskStatus(request3.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
28043
- this._clearTaskQueue(request3.params.taskId);
28044
- const cancelledTask = await this._taskStore.getTask(request3.params.taskId, extra.sessionId);
28491
+ await this._taskStore.updateTaskStatus(request4.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
28492
+ this._clearTaskQueue(request4.params.taskId);
28493
+ const cancelledTask = await this._taskStore.getTask(request4.params.taskId, extra.sessionId);
28045
28494
  if (!cancelledTask) {
28046
- throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request3.params.taskId}`);
28495
+ throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request4.params.taskId}`);
28047
28496
  }
28048
28497
  return {
28049
28498
  _meta: {},
@@ -28164,14 +28613,14 @@ var init_protocol = __esm({
28164
28613
  }
28165
28614
  Promise.resolve().then(() => handler(notification)).catch((error52) => this._onerror(new Error(`Uncaught error in notification handler: ${error52}`)));
28166
28615
  }
28167
- _onrequest(request3, extra) {
28168
- const handler = this._requestHandlers.get(request3.method) ?? this.fallbackRequestHandler;
28616
+ _onrequest(request4, extra) {
28617
+ const handler = this._requestHandlers.get(request4.method) ?? this.fallbackRequestHandler;
28169
28618
  const capturedTransport = this._transport;
28170
- const relatedTaskId = request3.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
28619
+ const relatedTaskId = request4.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
28171
28620
  if (handler === void 0) {
28172
28621
  const errorResponse = {
28173
28622
  jsonrpc: "2.0",
28174
- id: request3.id,
28623
+ id: request4.id,
28175
28624
  error: {
28176
28625
  code: ErrorCode.MethodNotFound,
28177
28626
  message: "Method not found"
@@ -28189,17 +28638,17 @@ var init_protocol = __esm({
28189
28638
  return;
28190
28639
  }
28191
28640
  const abortController = new AbortController();
28192
- this._requestHandlerAbortControllers.set(request3.id, abortController);
28193
- const taskCreationParams = isTaskAugmentedRequestParams(request3.params) ? request3.params.task : void 0;
28194
- const taskStore = this._taskStore ? this.requestTaskStore(request3, capturedTransport?.sessionId) : void 0;
28641
+ this._requestHandlerAbortControllers.set(request4.id, abortController);
28642
+ const taskCreationParams = isTaskAugmentedRequestParams(request4.params) ? request4.params.task : void 0;
28643
+ const taskStore = this._taskStore ? this.requestTaskStore(request4, capturedTransport?.sessionId) : void 0;
28195
28644
  const fullExtra = {
28196
28645
  signal: abortController.signal,
28197
28646
  sessionId: capturedTransport?.sessionId,
28198
- _meta: request3.params?._meta,
28647
+ _meta: request4.params?._meta,
28199
28648
  sendNotification: async (notification) => {
28200
28649
  if (abortController.signal.aborted)
28201
28650
  return;
28202
- const notificationOptions = { relatedRequestId: request3.id };
28651
+ const notificationOptions = { relatedRequestId: request4.id };
28203
28652
  if (relatedTaskId) {
28204
28653
  notificationOptions.relatedTask = { taskId: relatedTaskId };
28205
28654
  }
@@ -28209,7 +28658,7 @@ var init_protocol = __esm({
28209
28658
  if (abortController.signal.aborted) {
28210
28659
  throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
28211
28660
  }
28212
- const requestOptions = { ...options, relatedRequestId: request3.id };
28661
+ const requestOptions = { ...options, relatedRequestId: request4.id };
28213
28662
  if (relatedTaskId && !requestOptions.relatedTask) {
28214
28663
  requestOptions.relatedTask = { taskId: relatedTaskId };
28215
28664
  }
@@ -28220,7 +28669,7 @@ var init_protocol = __esm({
28220
28669
  return await this.request(r, resultSchema, requestOptions);
28221
28670
  },
28222
28671
  authInfo: extra?.authInfo,
28223
- requestId: request3.id,
28672
+ requestId: request4.id,
28224
28673
  requestInfo: extra?.requestInfo,
28225
28674
  taskId: relatedTaskId,
28226
28675
  taskStore,
@@ -28230,16 +28679,16 @@ var init_protocol = __esm({
28230
28679
  };
28231
28680
  Promise.resolve().then(() => {
28232
28681
  if (taskCreationParams) {
28233
- this.assertTaskHandlerCapability(request3.method);
28682
+ this.assertTaskHandlerCapability(request4.method);
28234
28683
  }
28235
- }).then(() => handler(request3, fullExtra)).then(async (result) => {
28684
+ }).then(() => handler(request4, fullExtra)).then(async (result) => {
28236
28685
  if (abortController.signal.aborted) {
28237
28686
  return;
28238
28687
  }
28239
28688
  const response = {
28240
28689
  result,
28241
28690
  jsonrpc: "2.0",
28242
- id: request3.id
28691
+ id: request4.id
28243
28692
  };
28244
28693
  if (relatedTaskId && this._taskMessageQueue) {
28245
28694
  await this._enqueueTaskMessage(relatedTaskId, {
@@ -28256,7 +28705,7 @@ var init_protocol = __esm({
28256
28705
  }
28257
28706
  const errorResponse = {
28258
28707
  jsonrpc: "2.0",
28259
- id: request3.id,
28708
+ id: request4.id,
28260
28709
  error: {
28261
28710
  code: Number.isSafeInteger(error52["code"]) ? error52["code"] : ErrorCode.InternalError,
28262
28711
  message: error52.message ?? "Internal error",
@@ -28273,8 +28722,8 @@ var init_protocol = __esm({
28273
28722
  await capturedTransport?.send(errorResponse);
28274
28723
  }
28275
28724
  }).catch((error52) => this._onerror(new Error(`Failed to send response: ${error52}`))).finally(() => {
28276
- if (this._requestHandlerAbortControllers.get(request3.id) === abortController) {
28277
- this._requestHandlerAbortControllers.delete(request3.id);
28725
+ if (this._requestHandlerAbortControllers.get(request4.id) === abortController) {
28726
+ this._requestHandlerAbortControllers.delete(request4.id);
28278
28727
  }
28279
28728
  });
28280
28729
  }
@@ -28378,11 +28827,11 @@ var init_protocol = __esm({
28378
28827
  *
28379
28828
  * @experimental Use `client.experimental.tasks.requestStream()` to access this method.
28380
28829
  */
28381
- async *requestStream(request3, resultSchema, options) {
28830
+ async *requestStream(request4, resultSchema, options) {
28382
28831
  const { task } = options ?? {};
28383
28832
  if (!task) {
28384
28833
  try {
28385
- const result = await this.request(request3, resultSchema, options);
28834
+ const result = await this.request(request4, resultSchema, options);
28386
28835
  yield { type: "result", result };
28387
28836
  } catch (error52) {
28388
28837
  yield {
@@ -28394,7 +28843,7 @@ var init_protocol = __esm({
28394
28843
  }
28395
28844
  let taskId;
28396
28845
  try {
28397
- const createResult = await this.request(request3, CreateTaskResultSchema, options);
28846
+ const createResult = await this.request(request4, CreateTaskResultSchema, options);
28398
28847
  if (createResult.task) {
28399
28848
  taskId = createResult.task.taskId;
28400
28849
  yield { type: "taskCreated", task: createResult.task };
@@ -28442,7 +28891,7 @@ var init_protocol = __esm({
28442
28891
  *
28443
28892
  * Do not use this method to emit notifications! Use notification() instead.
28444
28893
  */
28445
- request(request3, resultSchema, options) {
28894
+ request(request4, resultSchema, options) {
28446
28895
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
28447
28896
  return new Promise((resolve15, reject) => {
28448
28897
  const earlyReject = (error52) => {
@@ -28454,9 +28903,9 @@ var init_protocol = __esm({
28454
28903
  }
28455
28904
  if (this._options?.enforceStrictCapabilities === true) {
28456
28905
  try {
28457
- this.assertCapabilityForMethod(request3.method);
28906
+ this.assertCapabilityForMethod(request4.method);
28458
28907
  if (task) {
28459
- this.assertTaskCapability(request3.method);
28908
+ this.assertTaskCapability(request4.method);
28460
28909
  }
28461
28910
  } catch (e2) {
28462
28911
  earlyReject(e2);
@@ -28466,16 +28915,16 @@ var init_protocol = __esm({
28466
28915
  options?.signal?.throwIfAborted();
28467
28916
  const messageId = this._requestMessageId++;
28468
28917
  const jsonrpcRequest = {
28469
- ...request3,
28918
+ ...request4,
28470
28919
  jsonrpc: "2.0",
28471
28920
  id: messageId
28472
28921
  };
28473
28922
  if (options?.onprogress) {
28474
28923
  this._progressHandlers.set(messageId, options.onprogress);
28475
28924
  jsonrpcRequest.params = {
28476
- ...request3.params,
28925
+ ...request4.params,
28477
28926
  _meta: {
28478
- ...request3.params?._meta || {},
28927
+ ...request4.params?._meta || {},
28479
28928
  progressToken: messageId
28480
28929
  }
28481
28930
  };
@@ -28679,8 +29128,8 @@ var init_protocol = __esm({
28679
29128
  setRequestHandler(requestSchema, handler) {
28680
29129
  const method = getMethodLiteral(requestSchema);
28681
29130
  this.assertRequestHandlerCapability(method);
28682
- this._requestHandlers.set(method, (request3, extra) => {
28683
- const parsed = parseWithCompat(requestSchema, request3);
29131
+ this._requestHandlers.set(method, (request4, extra) => {
29132
+ const parsed = parseWithCompat(requestSchema, request4);
28684
29133
  return Promise.resolve(handler(parsed, extra));
28685
29134
  });
28686
29135
  }
@@ -28795,19 +29244,19 @@ var init_protocol = __esm({
28795
29244
  }, { once: true });
28796
29245
  });
28797
29246
  }
28798
- requestTaskStore(request3, sessionId) {
29247
+ requestTaskStore(request4, sessionId) {
28799
29248
  const taskStore = this._taskStore;
28800
29249
  if (!taskStore) {
28801
29250
  throw new Error("No task store configured");
28802
29251
  }
28803
29252
  return {
28804
29253
  createTask: async (taskParams) => {
28805
- if (!request3) {
29254
+ if (!request4) {
28806
29255
  throw new Error("No request provided");
28807
29256
  }
28808
- return await taskStore.createTask(taskParams, request3.id, {
28809
- method: request3.method,
28810
- params: request3.params
29257
+ return await taskStore.createTask(taskParams, request4.id, {
29258
+ method: request4.method,
29259
+ params: request4.params
28811
29260
  }, sessionId);
28812
29261
  },
28813
29262
  getTask: async (taskId) => {
@@ -32384,7 +32833,7 @@ var require_schemes = __commonJS({
32384
32833
  urnComponent.nss = (uuidComponent.uuid || "").toLowerCase();
32385
32834
  return urnComponent;
32386
32835
  }
32387
- var http10 = (
32836
+ var http11 = (
32388
32837
  /** @type {SchemeHandler} */
32389
32838
  {
32390
32839
  scheme: "http",
@@ -32397,7 +32846,7 @@ var require_schemes = __commonJS({
32397
32846
  /** @type {SchemeHandler} */
32398
32847
  {
32399
32848
  scheme: "https",
32400
- domainHost: http10.domainHost,
32849
+ domainHost: http11.domainHost,
32401
32850
  parse: httpParse,
32402
32851
  serialize: httpSerialize
32403
32852
  }
@@ -32441,7 +32890,7 @@ var require_schemes = __commonJS({
32441
32890
  var SCHEMES = (
32442
32891
  /** @type {Record<SchemeName, SchemeHandler>} */
32443
32892
  {
32444
- http: http10,
32893
+ http: http11,
32445
32894
  https: https6,
32446
32895
  ws,
32447
32896
  wss,
@@ -36034,93 +36483,86 @@ var init_connectCommand = __esm({
36034
36483
  }
36035
36484
  });
36036
36485
 
36037
- // src/server/cli/stopCommand.ts
36038
- var stopCommand_exports = {};
36039
- __export(stopCommand_exports, {
36040
- stopCommand: () => stopCommand
36486
+ // src/server/cli/restartCommand.ts
36487
+ var restartCommand_exports = {};
36488
+ __export(restartCommand_exports, {
36489
+ restartCommand: () => restartCommand
36041
36490
  });
36042
- function defaultIsProcessAlive(pid) {
36043
- try {
36044
- process.kill(pid, 0);
36045
- return true;
36046
- } catch (error52) {
36047
- return error52.code !== "ESRCH";
36491
+ function controlRequester(configDir) {
36492
+ const endpoint = readDaemonEndpointStatus(configDir);
36493
+ const token = readControlToken(configDir);
36494
+ if (endpoint.type !== "valid" || !token) {
36495
+ return void 0;
36048
36496
  }
36049
- }
36050
- async function stopCommand(configDir = resolveGrainHome(), clock = Date, processKiller = process.kill, adapter2 = createSupervisorAdapter(
36051
- process.platform,
36052
- createCommandRunner(),
36053
- process.getuid?.() ?? 0
36054
- ), isProcessAlive = defaultIsProcessAlive, platform2 = process.platform, requestStop = requestDaemonControlStop) {
36055
- if (await adapter2.isRegistered(DAEMON_SERVICE_IDENTITY)) {
36056
- console.error(
36057
- "Grain is installed as a background service. Run `grain uninstall` to remove it."
36497
+ const host = endpoint.record.host === "0.0.0.0" ? "127.0.0.1" : endpoint.record.host;
36498
+ return (method, path60, body) => new Promise((resolve15, reject) => {
36499
+ const payload = body === void 0 ? void 0 : JSON.stringify(body);
36500
+ const req = http7.request(
36501
+ {
36502
+ host,
36503
+ port: endpoint.record.port,
36504
+ path: path60,
36505
+ method,
36506
+ headers: {
36507
+ Authorization: `Bearer ${token}`,
36508
+ ...payload ? { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(payload) } : {}
36509
+ }
36510
+ },
36511
+ (res) => {
36512
+ let text = "";
36513
+ res.on("data", (chunk) => {
36514
+ text += chunk;
36515
+ });
36516
+ res.on("end", () => {
36517
+ try {
36518
+ resolve15({ status: res.statusCode ?? 0, body: JSON.parse(text) });
36519
+ } catch {
36520
+ resolve15({ status: res.statusCode ?? 0, body: text });
36521
+ }
36522
+ });
36523
+ }
36058
36524
  );
36059
- return 1;
36060
- }
36061
- const status = await readGrainServiceStatus(configDir);
36062
- if (!isRunningGrainService(status)) {
36063
- console.log("Grain is not running.");
36064
- return 0;
36065
- }
36066
- const pid = readDaemonEndpoint(configDir)?.pid;
36067
- if (pid === void 0) {
36068
- console.error("Could not determine Grain daemon PID.");
36069
- return 1;
36070
- }
36071
- const token = platform2 === "win32" ? readDaemonAuthToken(configDir) : void 0;
36072
- const accepted = token ? await requestStop(daemonControlEndpoint(configDir), token) : false;
36525
+ req.on("error", reject);
36526
+ req.setTimeout(5e3, () => req.destroy(new Error("timeout")));
36527
+ req.end(payload);
36528
+ });
36529
+ }
36530
+ async function stagedVersion(request4) {
36073
36531
  try {
36074
- if (!accepted) {
36075
- processKiller(pid, "SIGTERM");
36076
- }
36077
- } catch (error52) {
36078
- const code = error52.code;
36079
- if (code !== "ESRCH") {
36080
- console.error(`Could not signal Grain (pid ${pid}): ${code ?? String(error52)}`);
36081
- return 1;
36082
- }
36083
- }
36084
- const startMs = clock.now();
36085
- const timeoutMs = accepted ? drainStopBudgetMs(configDir) : 1e4;
36086
- while (clock.now() - startMs < timeoutMs) {
36087
- const currentStatus = await readGrainServiceStatus(configDir);
36088
- if (!isRunningGrainService(currentStatus) && !isProcessAlive(pid)) {
36089
- console.log("Grain stopped.");
36090
- return 0;
36091
- }
36092
- await new Promise((resolve15) => setTimeout(resolve15, 250));
36532
+ const { status, body } = await request4("GET", "/api/v1/update");
36533
+ const staged = body?.stagedVersion;
36534
+ return status === 200 && typeof staged === "string" ? staged : void 0;
36535
+ } catch {
36536
+ return void 0;
36093
36537
  }
36094
- console.error(`Grain did not stop within ${timeoutMs / 1e3} seconds.`);
36095
- return 1;
36096
36538
  }
36097
- var init_stopCommand = __esm({
36098
- "src/server/cli/stopCommand.ts"() {
36099
- "use strict";
36100
- init_grainHome();
36101
- init_daemonEndpointFile();
36102
- init_statusCommand();
36103
- init_supervisorAdapter();
36104
- init_daemonRecordInstance();
36105
- init_ipcEndpoint();
36106
- init_DaemonAuthToken();
36107
- init_requestDaemonControlStop();
36108
- init_drainStopBudget();
36539
+ async function restartCommand(configDir = resolveGrainHome(), request4 = controlRequester(configDir), write = (text) => process.stdout.write(text)) {
36540
+ const staged = request4 ? await stagedVersion(request4) : void 0;
36541
+ if (request4 && staged) {
36542
+ try {
36543
+ const { body } = await request4("POST", "/api/v1/update/restart", { discardResults: true });
36544
+ if (body?.result === "activated") {
36545
+ write(`Restarting Grain into ${staged}.
36546
+ `);
36547
+ return await startThroughService({ configHome: configDir, restart: false });
36548
+ }
36549
+ write(`Grain could not switch to ${staged} yet; restarting the current version.
36550
+ `);
36551
+ } catch {
36552
+ write(`Grain could not switch to ${staged} yet; restarting the current version.
36553
+ `);
36554
+ }
36109
36555
  }
36110
- });
36111
-
36112
- // src/server/cli/restartCommand.ts
36113
- var restartCommand_exports = {};
36114
- __export(restartCommand_exports, {
36115
- restartCommand: () => restartCommand
36116
- });
36117
- async function restartCommand(configDir = resolveGrainHome()) {
36118
36556
  return await startThroughService({ configHome: configDir, restart: true });
36119
36557
  }
36558
+ var http7;
36120
36559
  var init_restartCommand = __esm({
36121
36560
  "src/server/cli/restartCommand.ts"() {
36122
36561
  "use strict";
36562
+ http7 = __toESM(require("http"));
36123
36563
  init_grainHome();
36564
+ init_ControlToken();
36565
+ init_daemonEndpointFile();
36124
36566
  init_serviceControl();
36125
36567
  }
36126
36568
  });
@@ -36132,7 +36574,7 @@ __export(updateCommand_exports, {
36132
36574
  });
36133
36575
  function defaultRequester(host, port, token) {
36134
36576
  return new Promise((resolve15, reject) => {
36135
- const req = http7.request(
36577
+ const req = http8.request(
36136
36578
  {
36137
36579
  host: host === "0.0.0.0" ? "127.0.0.1" : host,
36138
36580
  port,
@@ -36191,11 +36633,11 @@ async function updateCommand(configDir = resolveGrainHome(), requester = default
36191
36633
  return 1;
36192
36634
  }
36193
36635
  }
36194
- var http7;
36636
+ var http8;
36195
36637
  var init_updateCommand = __esm({
36196
36638
  "src/server/cli/updateCommand.ts"() {
36197
36639
  "use strict";
36198
- http7 = __toESM(require("http"));
36640
+ http8 = __toESM(require("http"));
36199
36641
  init_grainHome();
36200
36642
  init_ControlToken();
36201
36643
  init_daemonEndpointFile();
@@ -58640,7 +59082,7 @@ var require_view = __commonJS({
58640
59082
  var debug = require_src()("express:view");
58641
59083
  var path60 = require("node:path");
58642
59084
  var fs58 = require("node:fs");
58643
- var dirname18 = path60.dirname;
59085
+ var dirname19 = path60.dirname;
58644
59086
  var basename5 = path60.basename;
58645
59087
  var extname = path60.extname;
58646
59088
  var join49 = path60.join;
@@ -58679,7 +59121,7 @@ var require_view = __commonJS({
58679
59121
  for (var i = 0; i < roots2.length && !path61; i++) {
58680
59122
  var root = roots2[i];
58681
59123
  var loc = resolve15(root, name);
58682
- var dir3 = dirname18(loc);
59124
+ var dir3 = dirname19(loc);
58683
59125
  var file5 = basename5(loc);
58684
59126
  path61 = this.resolve(dir3, file5);
58685
59127
  }
@@ -70367,7 +70809,7 @@ var require_application = __commonJS({
70367
70809
  var finalhandler = require_finalhandler();
70368
70810
  var debug = require_src()("express:application");
70369
70811
  var View2 = require_view();
70370
- var http10 = require("node:http");
70812
+ var http11 = require("node:http");
70371
70813
  var methods = require_utils4().methods;
70372
70814
  var compileETag = require_utils4().compileETag;
70373
70815
  var compileQueryParser = require_utils4().compileQueryParser;
@@ -70600,7 +71042,7 @@ var require_application = __commonJS({
70600
71042
  tryRender(view, renderOptions, done);
70601
71043
  };
70602
71044
  app.listen = function listen() {
70603
- var server = http10.createServer(this);
71045
+ var server = http11.createServer(this);
70604
71046
  var args = slice2.call(arguments);
70605
71047
  if (typeof args[args.length - 1] === "function") {
70606
71048
  var done = args[args.length - 1] = once(args[args.length - 1]);
@@ -71096,11 +71538,11 @@ var require_negotiator = __commonJS({
71096
71538
  var preferredMediaTypes = require_mediaType();
71097
71539
  module2.exports = Negotiator;
71098
71540
  module2.exports.Negotiator = Negotiator;
71099
- function Negotiator(request3) {
71541
+ function Negotiator(request4) {
71100
71542
  if (!(this instanceof Negotiator)) {
71101
- return new Negotiator(request3);
71543
+ return new Negotiator(request4);
71102
71544
  }
71103
- this.request = request3;
71545
+ this.request = request4;
71104
71546
  }
71105
71547
  Negotiator.prototype.charset = function charset(available) {
71106
71548
  var set4 = this.charsets(available);
@@ -80889,12 +81331,12 @@ var require_request = __commonJS({
80889
81331
  var accepts = require_accepts();
80890
81332
  var isIP = require("node:net").isIP;
80891
81333
  var typeis = require_type_is();
80892
- var http10 = require("node:http");
81334
+ var http11 = require("node:http");
80893
81335
  var fresh = require_fresh();
80894
81336
  var parseRange = require_range_parser();
80895
81337
  var parse7 = require_parseurl();
80896
81338
  var proxyaddr = require_proxy_addr();
80897
- var req = Object.create(http10.IncomingMessage.prototype);
81339
+ var req = Object.create(http11.IncomingMessage.prototype);
80898
81340
  module2.exports = req;
80899
81341
  req.get = req.header = function header(name) {
80900
81342
  if (!name) {
@@ -91471,7 +91913,7 @@ var require_response = __commonJS({
91471
91913
  var deprecate = require_depd()("express");
91472
91914
  var encodeUrl = require_encodeurl();
91473
91915
  var escapeHtml2 = require_escape_html();
91474
- var http10 = require("node:http");
91916
+ var http11 = require("node:http");
91475
91917
  var onFinished = require_on_finished();
91476
91918
  var mime = require_mime_types2();
91477
91919
  var path60 = require("node:path");
@@ -91487,7 +91929,7 @@ var require_response = __commonJS({
91487
91929
  var resolve15 = path60.resolve;
91488
91930
  var vary = require_vary();
91489
91931
  var { Buffer: Buffer2 } = require("node:buffer");
91490
- var res = Object.create(http10.ServerResponse.prototype);
91932
+ var res = Object.create(http11.ServerResponse.prototype);
91491
91933
  module2.exports = res;
91492
91934
  res.status = function status(code) {
91493
91935
  if (!Number.isInteger(code)) {
@@ -92295,93 +92737,6 @@ var init_DriverManager = __esm({
92295
92737
  }
92296
92738
  });
92297
92739
 
92298
- // src/services/featureFlags/FeatureFlagDefinitions.ts
92299
- var FEATURE_FLAGS;
92300
- var init_FeatureFlagDefinitions = __esm({
92301
- "src/services/featureFlags/FeatureFlagDefinitions.ts"() {
92302
- "use strict";
92303
- FEATURE_FLAGS = {
92304
- managedDuckDbRuntime: {
92305
- id: "sql_preview_managed_duckdb_runtime",
92306
- defaultValue: true,
92307
- description: "Gates background auto-provisioning of the managed DuckDB runtime (RFC-075).",
92308
- source: "local"
92309
- },
92310
- standaloneWebApp: {
92311
- id: "sql_preview_standalone_web_app",
92312
- defaultValue: true,
92313
- description: "Gates the local workbench serving route (RFC-163), opened with `grain ui`.",
92314
- source: "local"
92315
- },
92316
- charts: {
92317
- id: "sql_preview_charts",
92318
- defaultValue: false,
92319
- description: "Gates the chart representation UI and MCP chart tools (RFC-070).",
92320
- source: "posthog"
92321
- },
92322
- sessionReplay: {
92323
- id: "sql_preview_session_replay",
92324
- defaultValue: false,
92325
- description: "Gates masked PostHog session replay in VS Code webviews (RFC-069).",
92326
- source: "posthog"
92327
- },
92328
- executionLedger: {
92329
- id: "sql_preview_execution_ledger",
92330
- defaultValue: false,
92331
- description: "Gates local execution-ledger journaling and provenance capture (RFC-071).",
92332
- source: "posthog"
92333
- },
92334
- credentialRequiredSignal: {
92335
- id: "sql_preview_credential_required_signal",
92336
- defaultValue: true,
92337
- description: "Offers a one-time credential page on auth-failed queries (RFC-171).",
92338
- source: "local",
92339
- locked: true
92340
- },
92341
- crashDiagnostics: {
92342
- id: "sql_preview_crash_diagnostics",
92343
- defaultValue: true,
92344
- description: "Gates posthog-node exception autocapture on the daemon (RFC-092).",
92345
- source: "local"
92346
- },
92347
- mcpSurface: {
92348
- id: "sql_preview_mcp_surface",
92349
- defaultValue: false,
92350
- description: "Gates the generic MCP HTTP surface, requiring both entitlement and local consent (RFC-110).",
92351
- source: "posthog"
92352
- },
92353
- resultsCardRouting: {
92354
- id: "results-card-routing",
92355
- defaultValue: false,
92356
- description: "Gates two-view MCP result routing (RFC-167).",
92357
- source: "posthog"
92358
- }
92359
- };
92360
- }
92361
- });
92362
-
92363
- // src/services/featureFlags/isFeatureEnabled.ts
92364
- function isFeatureEnabled(key, env2 = process.env) {
92365
- const definition = FEATURE_FLAGS[key];
92366
- if (definition.locked) {
92367
- return definition.defaultValue;
92368
- }
92369
- const override = env2[`GRAIN_FF_${definition.id.toUpperCase()}`];
92370
- if (override === "1" || override === "true") {
92371
- return true;
92372
- }
92373
- if (override === "0" || override === "false") {
92374
- return false;
92375
- }
92376
- return definition.defaultValue;
92377
- }
92378
- var init_isFeatureEnabled = __esm({
92379
- "src/services/featureFlags/isFeatureEnabled.ts"() {
92380
- "use strict";
92381
- init_FeatureFlagDefinitions();
92382
- }
92383
- });
92384
-
92385
92740
  // src/server/publishBoundEndpoint.ts
92386
92741
  function publishBoundEndpoint(options) {
92387
92742
  const host = UNREACHABLE_BIND_HOSTS.includes(options.host) ? "127.0.0.1" : options.host;
@@ -92416,7 +92771,7 @@ function readExistingDaemonStatus(host, port, authToken) {
92416
92771
  settled = true;
92417
92772
  resolve15(status);
92418
92773
  };
92419
- const req = http8.get(
92774
+ const req = http9.get(
92420
92775
  {
92421
92776
  host,
92422
92777
  port,
@@ -92492,11 +92847,11 @@ async function checkForNewerDaemon(options) {
92492
92847
  checkingForSuccessor.delete(options.owner);
92493
92848
  }
92494
92849
  }
92495
- var http8, checkingForSuccessor;
92850
+ var http9, checkingForSuccessor;
92496
92851
  var init_daemonSuccession = __esm({
92497
92852
  "src/server/lifecycle/daemonSuccession.ts"() {
92498
92853
  "use strict";
92499
- http8 = __toESM(require("http"));
92854
+ http9 = __toESM(require("http"));
92500
92855
  init_daemonEndpointFile();
92501
92856
  init_daemonRecordInstance();
92502
92857
  init_ConsoleLogger();
@@ -92921,6 +93276,10 @@ var init_src = __esm({
92921
93276
  const setup = await created.connect();
92922
93277
  try {
92923
93278
  const { directories, files } = allowListExcluding(protectedDirectory);
93279
+ const demoDirectory = path36.join(realpathOrSelf(protectedDirectory), "demo", "data");
93280
+ if (realpathOrSelf(demoDirectory) === demoDirectory) {
93281
+ directories.push(demoDirectory + path36.sep);
93282
+ }
92924
93283
  await setup.run(`SET allowed_directories = ${sqlStringList(directories)}`);
92925
93284
  await setup.run(`SET allowed_paths = ${sqlStringList(files)}`);
92926
93285
  await setup.run("SET enable_external_access = false");
@@ -94046,8 +94405,8 @@ var init_AxiosError = __esm({
94046
94405
  init_AxiosHeaders();
94047
94406
  REDACTED = "[REDACTED ****]";
94048
94407
  AxiosError = class extends Error {
94049
- static from(error52, code, config2, request3, response, customProps) {
94050
- const axiosError = new AxiosError(error52.message, code || error52.code, config2, request3, response);
94408
+ static from(error52, code, config2, request4, response, customProps) {
94409
+ const axiosError = new AxiosError(error52.message, code || error52.code, config2, request4, response);
94051
94410
  axiosError.cause = error52;
94052
94411
  axiosError.name = error52.name;
94053
94412
  if (error52.status != null && axiosError.status == null) {
@@ -94067,7 +94426,7 @@ var init_AxiosError = __esm({
94067
94426
  *
94068
94427
  * @returns {Error} The created error.
94069
94428
  */
94070
- constructor(message, code, config2, request3, response) {
94429
+ constructor(message, code, config2, request4, response) {
94071
94430
  super(message);
94072
94431
  Object.defineProperty(this, "message", {
94073
94432
  // Null-proto descriptor so a polluted Object.prototype.get cannot turn
@@ -94082,7 +94441,7 @@ var init_AxiosError = __esm({
94082
94441
  this.isAxiosError = true;
94083
94442
  code && (this.code = code);
94084
94443
  config2 && (this.config = config2);
94085
- request3 && (this.request = request3);
94444
+ request4 && (this.request = request4);
94086
94445
  if (response) {
94087
94446
  this.response = response;
94088
94447
  this.status = response.status;
@@ -103286,7 +103645,7 @@ var require_form_data = __commonJS({
103286
103645
  var CombinedStream = require_combined_stream();
103287
103646
  var util3 = require("util");
103288
103647
  var path60 = require("path");
103289
- var http10 = require("http");
103648
+ var http11 = require("http");
103290
103649
  var https6 = require("https");
103291
103650
  var parseUrl2 = require("url").parse;
103292
103651
  var fs58 = require("fs");
@@ -103537,7 +103896,7 @@ var require_form_data = __commonJS({
103537
103896
  });
103538
103897
  };
103539
103898
  FormData3.prototype.submit = function(params, cb) {
103540
- var request3;
103899
+ var request4;
103541
103900
  var options;
103542
103901
  var defaults3 = { method: "post" };
103543
103902
  if (typeof params === "string") {
@@ -103556,9 +103915,9 @@ var require_form_data = __commonJS({
103556
103915
  }
103557
103916
  options.headers = this.getHeaders(params.headers);
103558
103917
  if (options.protocol === "https:") {
103559
- request3 = https6.request(options);
103918
+ request4 = https6.request(options);
103560
103919
  } else {
103561
- request3 = http10.request(options);
103920
+ request4 = http11.request(options);
103562
103921
  }
103563
103922
  this.getLength(function(err, length) {
103564
103923
  if (err && err !== "Unknown stream") {
@@ -103566,22 +103925,22 @@ var require_form_data = __commonJS({
103566
103925
  return;
103567
103926
  }
103568
103927
  if (length) {
103569
- request3.setHeader("Content-Length", length);
103928
+ request4.setHeader("Content-Length", length);
103570
103929
  }
103571
- this.pipe(request3);
103930
+ this.pipe(request4);
103572
103931
  if (cb) {
103573
103932
  var onResponse;
103574
103933
  var callback = function(error52, responce) {
103575
- request3.removeListener("error", callback);
103576
- request3.removeListener("response", onResponse);
103934
+ request4.removeListener("error", callback);
103935
+ request4.removeListener("response", onResponse);
103577
103936
  return cb.call(this, error52, responce);
103578
103937
  };
103579
103938
  onResponse = callback.bind(this, null);
103580
- request3.on("error", callback);
103581
- request3.on("response", onResponse);
103939
+ request4.on("error", callback);
103940
+ request4.on("response", onResponse);
103582
103941
  }
103583
103942
  }.bind(this));
103584
- return request3;
103943
+ return request4;
103585
103944
  };
103586
103945
  FormData3.prototype._error = function(err) {
103587
103946
  if (!this.error) {
@@ -104249,8 +104608,8 @@ var init_CanceledError = __esm({
104249
104608
  *
104250
104609
  * @returns {CanceledError} The created error.
104251
104610
  */
104252
- constructor(message, config2, request3) {
104253
- super(message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config2, request3);
104611
+ constructor(message, config2, request4) {
104612
+ super(message == null ? "canceled" : message, AxiosError_default.ERR_CANCELED, config2, request4);
104254
104613
  this.name = "CanceledError";
104255
104614
  this.__CANCEL__ = true;
104256
104615
  }
@@ -104418,7 +104777,7 @@ var require_follow_redirects = __commonJS({
104418
104777
  "node_modules/follow-redirects/index.js"(exports, module2) {
104419
104778
  var url3 = require("url");
104420
104779
  var URL3 = url3.URL;
104421
- var http10 = require("http");
104780
+ var http11 = require("http");
104422
104781
  var https6 = require("https");
104423
104782
  var Writable = require("stream").Writable;
104424
104783
  var assert3 = require("assert");
@@ -104673,10 +105032,10 @@ var require_follow_redirects = __commonJS({
104673
105032
  var scheme = protocol.slice(0, -1);
104674
105033
  this._options.agent = this._options.agents[scheme];
104675
105034
  }
104676
- var request3 = this._currentRequest = nativeProtocol.request(this._options, this._onNativeResponse);
104677
- request3._redirectable = this;
105035
+ var request4 = this._currentRequest = nativeProtocol.request(this._options, this._onNativeResponse);
105036
+ request4._redirectable = this;
104678
105037
  for (var event of events) {
104679
- request3.on(event, eventHandlers[event]);
105038
+ request4.on(event, eventHandlers[event]);
104680
105039
  }
104681
105040
  this._currentUrl = /^\//.test(this._options.path) ? url3.format(this._options) : (
104682
105041
  // When making a request to a proxy, […]
@@ -104688,16 +105047,16 @@ var require_follow_redirects = __commonJS({
104688
105047
  var self2 = this;
104689
105048
  var buffers = this._requestBodyBuffers;
104690
105049
  (function writeNext(error52) {
104691
- if (request3 === self2._currentRequest) {
105050
+ if (request4 === self2._currentRequest) {
104692
105051
  if (error52) {
104693
105052
  self2.emit("error", error52);
104694
105053
  } else if (i < buffers.length) {
104695
105054
  var buffer = buffers[i++];
104696
- if (!request3.finished) {
104697
- request3.write(buffer.data, buffer.encoding, writeNext);
105055
+ if (!request4.finished) {
105056
+ request4.write(buffer.data, buffer.encoding, writeNext);
104698
105057
  }
104699
105058
  } else if (self2._ended) {
104700
- request3.end();
105059
+ request4.end();
104701
105060
  }
104702
105061
  }
104703
105062
  })();
@@ -104779,7 +105138,7 @@ var require_follow_redirects = __commonJS({
104779
105138
  var protocol = scheme + ":";
104780
105139
  var nativeProtocol = nativeProtocols[protocol] = protocols[scheme];
104781
105140
  var wrappedProtocol = exports2[scheme] = Object.create(nativeProtocol);
104782
- function request3(input, options, callback) {
105141
+ function request4(input, options, callback) {
104783
105142
  if (isURL(input)) {
104784
105143
  input = spreadUrlObject(input);
104785
105144
  } else if (isString4(input)) {
@@ -104811,7 +105170,7 @@ var require_follow_redirects = __commonJS({
104811
105170
  return wrappedRequest;
104812
105171
  }
104813
105172
  Object.defineProperties(wrappedProtocol, {
104814
- request: { value: request3, configurable: true, enumerable: true, writable: true },
105173
+ request: { value: request4, configurable: true, enumerable: true, writable: true },
104815
105174
  get: { value: get6, configurable: true, enumerable: true, writable: true }
104816
105175
  });
104817
105176
  });
@@ -104889,12 +105248,12 @@ var require_follow_redirects = __commonJS({
104889
105248
  });
104890
105249
  return CustomError;
104891
105250
  }
104892
- function destroyRequest(request3, error52) {
105251
+ function destroyRequest(request4, error52) {
104893
105252
  for (var event of events) {
104894
- request3.removeListener(event, eventHandlers[event]);
105253
+ request4.removeListener(event, eventHandlers[event]);
104895
105254
  }
104896
- request3.on("error", noop4);
104897
- request3.destroy(error52);
105255
+ request4.on("error", noop4);
105256
+ request4.destroy(error52);
104898
105257
  }
104899
105258
  function isSubdomain(subdomain, domain2) {
104900
105259
  assert3(isString4(subdomain) && isString4(domain2));
@@ -104919,7 +105278,7 @@ var require_follow_redirects = __commonJS({
104919
105278
  function escapeRegex2(regex) {
104920
105279
  return regex.replace(/[\]\\/()*+?.$]/g, "\\$&");
104921
105280
  }
104922
- module2.exports = wrap({ http: http10, https: https6 });
105281
+ module2.exports = wrap({ http: http11, https: https6 });
104923
105282
  module2.exports.wrap = wrap;
104924
105283
  }
104925
105284
  });
@@ -106791,24 +107150,24 @@ var init_xhr = __esm({
106791
107150
  _config.cancelToken && _config.cancelToken.unsubscribe(onCanceled);
106792
107151
  _config.signal && _config.signal.removeEventListener("abort", onCanceled);
106793
107152
  }
106794
- let request3 = new XMLHttpRequest();
106795
- request3.open(_config.method.toUpperCase(), _config.url, true);
106796
- request3.timeout = _config.timeout;
107153
+ let request4 = new XMLHttpRequest();
107154
+ request4.open(_config.method.toUpperCase(), _config.url, true);
107155
+ request4.timeout = _config.timeout;
106797
107156
  function onloadend() {
106798
- if (!request3) {
107157
+ if (!request4) {
106799
107158
  return;
106800
107159
  }
106801
107160
  const responseHeaders = AxiosHeaders_default.from(
106802
- "getAllResponseHeaders" in request3 && request3.getAllResponseHeaders()
107161
+ "getAllResponseHeaders" in request4 && request4.getAllResponseHeaders()
106803
107162
  );
106804
- const responseData = !responseType || responseType === "text" || responseType === "json" ? request3.responseText : request3.response;
107163
+ const responseData = !responseType || responseType === "text" || responseType === "json" ? request4.responseText : request4.response;
106805
107164
  const response = {
106806
107165
  data: responseData,
106807
- status: request3.status,
106808
- statusText: request3.statusText,
107166
+ status: request4.status,
107167
+ statusText: request4.statusText,
106809
107168
  headers: responseHeaders,
106810
107169
  config: config2,
106811
- request: request3
107170
+ request: request4
106812
107171
  };
106813
107172
  settle(
106814
107173
  function _resolve(value) {
@@ -106821,38 +107180,38 @@ var init_xhr = __esm({
106821
107180
  },
106822
107181
  response
106823
107182
  );
106824
- request3 = null;
107183
+ request4 = null;
106825
107184
  }
106826
- if ("onloadend" in request3) {
106827
- request3.onloadend = onloadend;
107185
+ if ("onloadend" in request4) {
107186
+ request4.onloadend = onloadend;
106828
107187
  } else {
106829
- request3.onreadystatechange = function handleLoad() {
106830
- if (!request3 || request3.readyState !== 4) {
107188
+ request4.onreadystatechange = function handleLoad() {
107189
+ if (!request4 || request4.readyState !== 4) {
106831
107190
  return;
106832
107191
  }
106833
- if (request3.status === 0 && !(request3.responseURL && request3.responseURL.startsWith("file:"))) {
107192
+ if (request4.status === 0 && !(request4.responseURL && request4.responseURL.startsWith("file:"))) {
106834
107193
  return;
106835
107194
  }
106836
107195
  setTimeout(onloadend);
106837
107196
  };
106838
107197
  }
106839
- request3.onabort = function handleAbort() {
106840
- if (!request3) {
107198
+ request4.onabort = function handleAbort() {
107199
+ if (!request4) {
106841
107200
  return;
106842
107201
  }
106843
- reject(new AxiosError_default("Request aborted", AxiosError_default.ECONNABORTED, config2, request3));
107202
+ reject(new AxiosError_default("Request aborted", AxiosError_default.ECONNABORTED, config2, request4));
106844
107203
  done();
106845
- request3 = null;
107204
+ request4 = null;
106846
107205
  };
106847
- request3.onerror = function handleError(event) {
107206
+ request4.onerror = function handleError(event) {
106848
107207
  const msg = event && event.message ? event.message : "Network Error";
106849
- const err = new AxiosError_default(msg, AxiosError_default.ERR_NETWORK, config2, request3);
107208
+ const err = new AxiosError_default(msg, AxiosError_default.ERR_NETWORK, config2, request4);
106850
107209
  err.event = event || null;
106851
107210
  reject(err);
106852
107211
  done();
106853
- request3 = null;
107212
+ request4 = null;
106854
107213
  };
106855
- request3.ontimeout = function handleTimeout() {
107214
+ request4.ontimeout = function handleTimeout() {
106856
107215
  let timeoutErrorMessage = _config.timeout ? "timeout of " + _config.timeout + "ms exceeded" : "timeout exceeded";
106857
107216
  const transitional2 = _config.transitional || transitional_default;
106858
107217
  if (_config.timeoutErrorMessage) {
@@ -106863,42 +107222,42 @@ var init_xhr = __esm({
106863
107222
  timeoutErrorMessage,
106864
107223
  transitional2.clarifyTimeoutError ? AxiosError_default.ETIMEDOUT : AxiosError_default.ECONNABORTED,
106865
107224
  config2,
106866
- request3
107225
+ request4
106867
107226
  )
106868
107227
  );
106869
107228
  done();
106870
- request3 = null;
107229
+ request4 = null;
106871
107230
  };
106872
107231
  requestData === void 0 && requestHeaders.setContentType(null);
106873
- if ("setRequestHeader" in request3) {
107232
+ if ("setRequestHeader" in request4) {
106874
107233
  utils_default.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) {
106875
- request3.setRequestHeader(key, val);
107234
+ request4.setRequestHeader(key, val);
106876
107235
  });
106877
107236
  }
106878
107237
  if (!utils_default.isUndefined(_config.withCredentials)) {
106879
- request3.withCredentials = !!_config.withCredentials;
107238
+ request4.withCredentials = !!_config.withCredentials;
106880
107239
  }
106881
107240
  if (responseType && responseType !== "json") {
106882
- request3.responseType = _config.responseType;
107241
+ request4.responseType = _config.responseType;
106883
107242
  }
106884
107243
  if (onDownloadProgress) {
106885
107244
  [downloadThrottled, flushDownload] = progressEventReducer(onDownloadProgress, true);
106886
- request3.addEventListener("progress", downloadThrottled);
107245
+ request4.addEventListener("progress", downloadThrottled);
106887
107246
  }
106888
- if (onUploadProgress && request3.upload) {
107247
+ if (onUploadProgress && request4.upload) {
106889
107248
  [uploadThrottled, flushUpload] = progressEventReducer(onUploadProgress);
106890
- request3.upload.addEventListener("progress", uploadThrottled);
106891
- request3.upload.addEventListener("loadend", flushUpload);
107249
+ request4.upload.addEventListener("progress", uploadThrottled);
107250
+ request4.upload.addEventListener("loadend", flushUpload);
106892
107251
  }
106893
107252
  if (_config.cancelToken || _config.signal) {
106894
107253
  onCanceled = (cancel) => {
106895
- if (!request3) {
107254
+ if (!request4) {
106896
107255
  return;
106897
107256
  }
106898
- reject(!cancel || cancel.type ? new CanceledError_default(null, config2, request3) : cancel);
106899
- request3.abort();
107257
+ reject(!cancel || cancel.type ? new CanceledError_default(null, config2, request4) : cancel);
107258
+ request4.abort();
106900
107259
  done();
106901
- request3 = null;
107260
+ request4 = null;
106902
107261
  };
106903
107262
  _config.cancelToken && _config.cancelToken.subscribe(onCanceled);
106904
107263
  if (_config.signal) {
@@ -106916,7 +107275,7 @@ var init_xhr = __esm({
106916
107275
  );
106917
107276
  return;
106918
107277
  }
106919
- request3.send(requestData || null);
107278
+ request4.send(requestData || null);
106920
107279
  });
106921
107280
  };
106922
107281
  }
@@ -107101,7 +107460,7 @@ var init_fetch = __esm({
107101
107460
  const encodeText = isFetchSupported && (typeof TextEncoder2 === "function" ? ((encoder) => (str) => encoder.encode(str))(new TextEncoder2()) : async (str) => new Uint8Array(await new Request3(str).arrayBuffer()));
107102
107461
  const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => {
107103
107462
  let duplexAccessed = false;
107104
- const request3 = new Request3(platform_default.origin, {
107463
+ const request4 = new Request3(platform_default.origin, {
107105
107464
  body: new ReadableStream2(),
107106
107465
  method: "POST",
107107
107466
  get duplex() {
@@ -107109,9 +107468,9 @@ var init_fetch = __esm({
107109
107468
  return "half";
107110
107469
  }
107111
107470
  });
107112
- const hasContentType = request3.headers.has("Content-Type");
107113
- if (request3.body != null) {
107114
- request3.body.cancel();
107471
+ const hasContentType = request4.headers.has("Content-Type");
107472
+ if (request4.body != null) {
107473
+ request4.body.cancel();
107115
107474
  }
107116
107475
  return duplexAccessed && !hasContentType;
107117
107476
  });
@@ -107187,7 +107546,7 @@ var init_fetch = __esm({
107187
107546
  [signal, cancelToken && cancelToken.toAbortSignal()],
107188
107547
  timeout
107189
107548
  );
107190
- let request3 = null;
107549
+ let request4 = null;
107191
107550
  const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => {
107192
107551
  composedSignal.unsubscribe();
107193
107552
  });
@@ -107200,7 +107559,7 @@ var init_fetch = __esm({
107200
107559
  "maxContentLength size of " + maxContentLength + " exceeded",
107201
107560
  AxiosError_default.ERR_BAD_RESPONSE,
107202
107561
  config2,
107203
- request3
107562
+ request4
107204
107563
  );
107205
107564
  }
107206
107565
  }
@@ -107211,7 +107570,7 @@ var init_fetch = __esm({
107211
107570
  "Request body larger than maxBodyLength limit",
107212
107571
  AxiosError_default.ERR_BAD_REQUEST,
107213
107572
  config2,
107214
- request3
107573
+ request4
107215
107574
  );
107216
107575
  }
107217
107576
  }
@@ -107253,8 +107612,8 @@ var init_fetch = __esm({
107253
107612
  duplex: "half",
107254
107613
  credentials: isCredentialsSupported ? withCredentials : void 0
107255
107614
  };
107256
- request3 = isRequestSupported && new Request3(url3, resolvedOptions);
107257
- let response = await (isRequestSupported ? _fetch(request3, fetchOptions) : _fetch(url3, resolvedOptions));
107615
+ request4 = isRequestSupported && new Request3(url3, resolvedOptions);
107616
+ let response = await (isRequestSupported ? _fetch(request4, fetchOptions) : _fetch(url3, resolvedOptions));
107258
107617
  if (hasMaxContentLength) {
107259
107618
  const declaredLength = utils_default.toFiniteNumber(response.headers.get("content-length"));
107260
107619
  if (declaredLength != null && declaredLength > maxContentLength) {
@@ -107262,7 +107621,7 @@ var init_fetch = __esm({
107262
107621
  "maxContentLength size of " + maxContentLength + " exceeded",
107263
107622
  AxiosError_default.ERR_BAD_RESPONSE,
107264
107623
  config2,
107265
- request3
107624
+ request4
107266
107625
  );
107267
107626
  }
107268
107627
  }
@@ -107286,7 +107645,7 @@ var init_fetch = __esm({
107286
107645
  "maxContentLength size of " + maxContentLength + " exceeded",
107287
107646
  AxiosError_default.ERR_BAD_RESPONSE,
107288
107647
  config2,
107289
- request3
107648
+ request4
107290
107649
  );
107291
107650
  }
107292
107651
  }
@@ -107321,7 +107680,7 @@ var init_fetch = __esm({
107321
107680
  "maxContentLength size of " + maxContentLength + " exceeded",
107322
107681
  AxiosError_default.ERR_BAD_RESPONSE,
107323
107682
  config2,
107324
- request3
107683
+ request4
107325
107684
  );
107326
107685
  }
107327
107686
  }
@@ -107333,7 +107692,7 @@ var init_fetch = __esm({
107333
107692
  status: response.status,
107334
107693
  statusText: response.statusText,
107335
107694
  config: config2,
107336
- request: request3
107695
+ request: request4
107337
107696
  });
107338
107697
  });
107339
107698
  } catch (err) {
@@ -107341,7 +107700,7 @@ var init_fetch = __esm({
107341
107700
  if (composedSignal && composedSignal.aborted && composedSignal.reason instanceof AxiosError_default) {
107342
107701
  const canceledError = composedSignal.reason;
107343
107702
  canceledError.config = config2;
107344
- request3 && (canceledError.request = request3);
107703
+ request4 && (canceledError.request = request4);
107345
107704
  err !== canceledError && (canceledError.cause = err);
107346
107705
  throw canceledError;
107347
107706
  }
@@ -107351,7 +107710,7 @@ var init_fetch = __esm({
107351
107710
  "Network Error",
107352
107711
  AxiosError_default.ERR_NETWORK,
107353
107712
  config2,
107354
- request3,
107713
+ request4,
107355
107714
  err && err.response
107356
107715
  ),
107357
107716
  {
@@ -107359,7 +107718,7 @@ var init_fetch = __esm({
107359
107718
  }
107360
107719
  );
107361
107720
  }
107362
- throw AxiosError_default.from(err, err && err.code, config2, request3, err && err.response);
107721
+ throw AxiosError_default.from(err, err && err.code, config2, request4, err && err.response);
107363
107722
  }
107364
107723
  };
107365
107724
  };
@@ -107846,11 +108205,11 @@ var init_CancelToken = __esm({
107846
108205
  };
107847
108206
  return promise2;
107848
108207
  };
107849
- executor(function cancel(message, config2, request3) {
108208
+ executor(function cancel(message, config2, request4) {
107850
108209
  if (token.reason) {
107851
108210
  return;
107852
108211
  }
107853
- token.reason = new CanceledError_default(message, config2, request3);
108212
+ token.reason = new CanceledError_default(message, config2, request4);
107854
108213
  resolvePromise(token.reason);
107855
108214
  });
107856
108215
  }
@@ -111583,11 +111942,11 @@ var init_src7 = __esm({
111583
111942
  pool: { max: 1, min: 0, idleTimeoutMillis: 2e3 }
111584
111943
  });
111585
111944
  try {
111586
- const request3 = pool.request();
111945
+ const request4 = pool.request();
111587
111946
  for (const [key, value] of Object.entries(params)) {
111588
- request3.input(key, value);
111947
+ request4.input(key, value);
111589
111948
  }
111590
- const result = await request3.query(sql);
111949
+ const result = await request4.query(sql);
111591
111950
  const recordset = result.recordset ?? [];
111592
111951
  if (recordset.length === 0) {
111593
111952
  return [];
@@ -112438,14 +112797,14 @@ var init_ElasticsearchConnector = __esm({
112438
112797
  const validationError = this.validateConfig(config2);
112439
112798
  if (validationError)
112440
112799
  throw new import_connector_api9.ConnectionError(validationError);
112441
- const request3 = this.requestConfig(config2, authHeader, abortSignal);
112800
+ const request4 = this.requestConfig(config2, authHeader, abortSignal);
112442
112801
  let cursor;
112443
112802
  let cursorToClose;
112444
112803
  try {
112445
112804
  let response = await this.postSql(
112446
112805
  this.baseUrl(config2),
112447
112806
  { query, fetch_size: 1e3, field_multi_value_leniency: true },
112448
- request3,
112807
+ request4,
112449
112808
  query
112450
112809
  );
112451
112810
  cursor = response.cursor;
@@ -112456,7 +112815,7 @@ var init_ElasticsearchConnector = __esm({
112456
112815
  response = await this.postSql(
112457
112816
  this.baseUrl(config2),
112458
112817
  { cursor: requestedCursor },
112459
- request3,
112818
+ request4,
112460
112819
  query
112461
112820
  );
112462
112821
  cursor = response.cursor;
@@ -112466,7 +112825,7 @@ var init_ElasticsearchConnector = __esm({
112466
112825
  }
112467
112826
  } finally {
112468
112827
  if (cursorToClose)
112469
- await this.clearCursor(this.baseUrl(config2), cursorToClose, request3);
112828
+ await this.clearCursor(this.baseUrl(config2), cursorToClose, request4);
112470
112829
  }
112471
112830
  }
112472
112831
  async testConnection(config2, authHeader) {
@@ -112562,12 +112921,12 @@ var init_ElasticsearchConnector = __esm({
112562
112921
  return password ? `ApiKey ${password}` : void 0;
112563
112922
  return config2.user && password ? `Basic ${Buffer.from(`${config2.user}:${password}`).toString("base64")}` : void 0;
112564
112923
  }
112565
- async postSql(baseUrl, body, request3, query) {
112924
+ async postSql(baseUrl, body, request4, query) {
112566
112925
  try {
112567
112926
  const response = await axios_default.post(
112568
112927
  `${baseUrl}/_sql?format=json`,
112569
112928
  body,
112570
- request3
112929
+ request4
112571
112930
  );
112572
112931
  if (response.status >= 400)
112573
112932
  this.throwHttpError(response.status, response.data, query);
@@ -112584,8 +112943,8 @@ var init_ElasticsearchConnector = __esm({
112584
112943
  supportsPagination: true
112585
112944
  };
112586
112945
  }
112587
- async clearCursor(baseUrl, cursor, request3) {
112588
- const closeRequest = { ...request3 };
112946
+ async clearCursor(baseUrl, cursor, request4) {
112947
+ const closeRequest = { ...request4 };
112589
112948
  delete closeRequest.signal;
112590
112949
  try {
112591
112950
  await axios_default.post(`${baseUrl}/_sql/close`, { cursor }, closeRequest);
@@ -113366,7 +113725,17 @@ if (parentPort) {
113366
113725
  });
113367
113726
 
113368
113727
  // src/server/connection/KeychainCredentialStore.ts
113728
+ function isNativeKeychainForbiddenError(error52) {
113729
+ return error52 instanceof Error && error52.code === NATIVE_KEYCHAIN_FORBIDDEN_CODE;
113730
+ }
113369
113731
  function resolveDefaultKeyringModule() {
113732
+ if (process.env["GRAIN_TEST_FORBID_NATIVE_KEYCHAIN"] === "1") {
113733
+ const testKeyringModulePath = process.env["GRAIN_TEST_KEYRING_MODULE_PATH"];
113734
+ if (testKeyringModulePath) {
113735
+ return testKeyringModulePath;
113736
+ }
113737
+ throw new NativeKeychainForbiddenError();
113738
+ }
113370
113739
  require("@napi-rs/keyring/keytar");
113371
113740
  return require.resolve("@napi-rs/keyring/keytar");
113372
113741
  }
@@ -113380,7 +113749,7 @@ function describeProbeFailure(error52) {
113380
113749
  detail
113381
113750
  };
113382
113751
  }
113383
- var SERVICE_NAME, PROBE_ACCOUNT, DEFAULT_TIMEOUT_MS, MAX_DETAIL_LENGTH, KeychainCredentialStore;
113752
+ var SERVICE_NAME, PROBE_ACCOUNT, DEFAULT_TIMEOUT_MS, NATIVE_KEYCHAIN_FORBIDDEN_CODE, NativeKeychainForbiddenError, MAX_DETAIL_LENGTH, KeychainCredentialStore;
113384
113753
  var init_KeychainCredentialStore = __esm({
113385
113754
  "src/server/connection/KeychainCredentialStore.ts"() {
113386
113755
  "use strict";
@@ -113389,6 +113758,16 @@ var init_KeychainCredentialStore = __esm({
113389
113758
  SERVICE_NAME = "Grain";
113390
113759
  PROBE_ACCOUNT = "__sql_preview_keychain_probe__";
113391
113760
  DEFAULT_TIMEOUT_MS = 5e3;
113761
+ NATIVE_KEYCHAIN_FORBIDDEN_CODE = "GRAIN_TEST_NATIVE_KEYCHAIN_FORBIDDEN";
113762
+ NativeKeychainForbiddenError = class extends Error {
113763
+ constructor() {
113764
+ super(
113765
+ "Native keychain access is forbidden in tests because GRAIN_TEST_FORBID_NATIVE_KEYCHAIN=1; configure GRAIN_TEST_KEYRING_MODULE_PATH to use a test keyring."
113766
+ );
113767
+ this.code = NATIVE_KEYCHAIN_FORBIDDEN_CODE;
113768
+ this.name = "NativeKeychainForbiddenError";
113769
+ }
113770
+ };
113392
113771
  MAX_DETAIL_LENGTH = 200;
113393
113772
  KeychainCredentialStore = class {
113394
113773
  constructor(fallback, options = {}) {
@@ -113419,6 +113798,9 @@ var init_KeychainCredentialStore = __esm({
113419
113798
  await invokeWorker(modulePath, "deletePassword", [SERVICE_NAME, PROBE_ACCOUNT], timeoutMs);
113420
113799
  return { available: true };
113421
113800
  } catch (error52) {
113801
+ if (isNativeKeychainForbiddenError(error52)) {
113802
+ throw error52;
113803
+ }
113422
113804
  logger.warn("[KeychainCredentialStore] Probe failed; will use file fallback", error52);
113423
113805
  return { available: false, ...describeProbeFailure(error52) };
113424
113806
  }
@@ -113436,6 +113818,9 @@ var init_KeychainCredentialStore = __esm({
113436
113818
  );
113437
113819
  return typeof password === "string" ? password : this.fallback.getPassword(profileId);
113438
113820
  } catch (error52) {
113821
+ if (isNativeKeychainForbiddenError(error52)) {
113822
+ throw error52;
113823
+ }
113439
113824
  if (error52 instanceof KeychainTimeoutError) {
113440
113825
  throw error52;
113441
113826
  }
@@ -113455,6 +113840,9 @@ var init_KeychainCredentialStore = __esm({
113455
113840
  this.timeoutMs
113456
113841
  );
113457
113842
  } catch (error52) {
113843
+ if (isNativeKeychainForbiddenError(error52)) {
113844
+ throw error52;
113845
+ }
113458
113846
  if (error52 instanceof KeychainTimeoutError) {
113459
113847
  throw error52;
113460
113848
  }
@@ -113474,6 +113862,9 @@ var init_KeychainCredentialStore = __esm({
113474
113862
  this.timeoutMs
113475
113863
  );
113476
113864
  } catch (error52) {
113865
+ if (isNativeKeychainForbiddenError(error52)) {
113866
+ throw error52;
113867
+ }
113477
113868
  if (error52 instanceof KeychainTimeoutError) {
113478
113869
  throw error52;
113479
113870
  }
@@ -114641,49 +115032,49 @@ var init_QueryOperationRunner = __esm({
114641
115032
  detachAbortForwarder();
114642
115033
  }
114643
115034
  }
114644
- async run(request3) {
115035
+ async run(request4) {
114645
115036
  const releaseAdmission = this.admission.acquire();
114646
115037
  let prepared;
114647
115038
  try {
114648
- prepared = this.prepareQueryOperation(request3);
115039
+ prepared = this.prepareQueryOperation(request4);
114649
115040
  } catch (error52) {
114650
115041
  releaseAdmission();
114651
- if (errorIdOf(error52) === "query_result_tab_limit" && request3.origin !== void 0 && isDaemonEmittedOrigin(request3.origin)) {
115042
+ if (errorIdOf(error52) === "query_result_tab_limit" && request4.origin !== void 0 && isDaemonEmittedOrigin(request4.origin)) {
114652
115043
  this.telemetry?.capture(
114653
115044
  "query_failed",
114654
115045
  {
114655
115046
  state: "daemon",
114656
- source: isAgentOrigin(request3.origin) ? "mcp" : "unknown",
114657
- statement_type: classifySqlStatement(request3.sql),
115047
+ source: isAgentOrigin(request4.origin) ? "mcp" : "unknown",
115048
+ statement_type: classifySqlStatement(request4.sql),
114658
115049
  duration_bucket: bucketDurationMs(0),
114659
- query_length_bucket: bucketQueryLength(request3.sql.length),
114660
- connector: normalizeTelemetryConnector(request3.connectionProfile?.type),
115050
+ query_length_bucket: bucketQueryLength(request4.sql.length),
115051
+ connector: normalizeTelemetryConnector(request4.connectionProfile?.type),
114661
115052
  error_kind: "unknown",
114662
115053
  error_id: "query_result_tab_limit"
114663
115054
  },
114664
- request3.clientConsent
115055
+ request4.clientConsent
114665
115056
  );
114666
115057
  }
114667
115058
  throw error52;
114668
115059
  }
114669
- const waitForResult = request3.waitForResult ?? true;
115060
+ const waitForResult = request4.waitForResult ?? true;
114670
115061
  const controller = new AbortController();
114671
- const detachAbortForwarder = this.forwardAbort(request3.abortSignal, controller);
115062
+ const detachAbortForwarder = this.forwardAbort(request4.abortSignal, controller);
114672
115063
  this.abortRunningQuery(prepared.session, prepared.tabId);
114673
115064
  this.sessionManager.registerOperation(controller, prepared.session.id, prepared.tabId);
114674
115065
  const executionPromise = this.executeAndStore(
114675
115066
  prepared.session.id,
114676
115067
  prepared.tabId,
114677
115068
  prepared.sql,
114678
- request3.connectionId,
114679
- request3.connectionProfile,
114680
- request3.authHeader,
115069
+ request4.connectionId,
115070
+ request4.connectionProfile,
115071
+ request4.authHeader,
114681
115072
  controller,
114682
- request3.origin,
114683
- request3.loadAllRows,
114684
- request3.enforceReadOnly,
114685
- request3.clientConsent,
114686
- request3.workspaceRoot
115073
+ request4.origin,
115074
+ request4.loadAllRows,
115075
+ request4.enforceReadOnly,
115076
+ request4.clientConsent,
115077
+ request4.workspaceRoot
114687
115078
  ).finally(() => {
114688
115079
  releaseAdmission();
114689
115080
  this.sessionManager.unregisterOperation(controller);
@@ -114743,12 +115134,12 @@ var init_QueryOperationRunner = __esm({
114743
115134
  this.sessionManager.removeTab(sessionId, tabId);
114744
115135
  session.lastActivityAt = /* @__PURE__ */ new Date();
114745
115136
  }
114746
- getTabInfo(request3) {
114747
- const session = this.sessionManager.getSession(request3.sessionId);
115137
+ getTabInfo(request4) {
115138
+ const session = this.sessionManager.getSession(request4.sessionId);
114748
115139
  if (!session) {
114749
115140
  throw new Error("Session not found");
114750
115141
  }
114751
- const tabId = request3.tabId || session.activeTabId;
115142
+ const tabId = request4.tabId || session.activeTabId;
114752
115143
  if (!tabId) {
114753
115144
  return void 0;
114754
115145
  }
@@ -114756,14 +115147,14 @@ var init_QueryOperationRunner = __esm({
114756
115147
  if (!tab) {
114757
115148
  return void 0;
114758
115149
  }
114759
- const mode = request3.mode || "preview";
115150
+ const mode = request4.mode || "preview";
114760
115151
  const totalRows = tab.rows?.length ?? 0;
114761
- const resourceUri = `sql-preview://sessions/${request3.sessionId}/tabs/${tabId}`;
115152
+ const resourceUri = `sql-preview://sessions/${request4.sessionId}/tabs/${tabId}`;
114762
115153
  if (mode === "preview") {
114763
- const previewLimit = request3.limit || 10;
115154
+ const previewLimit = request4.limit || 10;
114764
115155
  const previewRows = tab.rows ? tab.rows.slice(0, previewLimit) : [];
114765
115156
  return {
114766
- sessionId: request3.sessionId,
115157
+ sessionId: request4.sessionId,
114767
115158
  tabId,
114768
115159
  status: tab.status,
114769
115160
  meta: {
@@ -114782,8 +115173,8 @@ var init_QueryOperationRunner = __esm({
114782
115173
  ...tab.wasTruncated !== void 0 ? { wasTruncated: tab.wasTruncated } : {}
114783
115174
  };
114784
115175
  }
114785
- const offset = request3.offset || 0;
114786
- const limit = request3.limit ?? 100;
115176
+ const offset = request4.offset || 0;
115177
+ const limit = request4.limit ?? 100;
114787
115178
  const candidateRows = tab.rows ? tab.rows.slice(offset, offset + limit) : [];
114788
115179
  const rows = [];
114789
115180
  let currentSizeBytes = 0;
@@ -114798,7 +115189,7 @@ var init_QueryOperationRunner = __esm({
114798
115189
  const hasMore = offset + rows.length < totalRows;
114799
115190
  return {
114800
115191
  id: tab.id,
114801
- sessionId: request3.sessionId,
115192
+ sessionId: request4.sessionId,
114802
115193
  tabId,
114803
115194
  title: tab.title,
114804
115195
  status: tab.status,
@@ -114820,38 +115211,38 @@ var init_QueryOperationRunner = __esm({
114820
115211
  ...tab.wasTruncated !== void 0 ? { wasTruncated: tab.wasTruncated } : {}
114821
115212
  };
114822
115213
  }
114823
- prepareQueryOperation(request3) {
114824
- const sql = request3.sql.trim();
115214
+ prepareQueryOperation(request4) {
115215
+ const sql = request4.sql.trim();
114825
115216
  if (!sql) {
114826
115217
  throw new Error("SQL query is required");
114827
115218
  }
114828
- let session = this.sessionManager.getSession(request3.sessionId);
115219
+ let session = this.sessionManager.getSession(request4.sessionId);
114829
115220
  if (!session) {
114830
115221
  logger.info("Session not found, auto-registering...");
114831
- const isEditor = request3.origin === "vscode_extension" || request3.displayName === "VS Code";
115222
+ const isEditor = request4.origin === "vscode_extension" || request4.displayName === "VS Code";
114832
115223
  this.sessionManager.registerSession(
114833
- request3.sessionId,
114834
- request3.displayName || (isEditor ? "VS Code" : "MCP Client"),
115224
+ request4.sessionId,
115225
+ request4.displayName || (isEditor ? "VS Code" : "MCP Client"),
114835
115226
  isEditor ? "vscode" : "standalone"
114836
115227
  );
114837
- session = this.sessionManager.getSession(request3.sessionId);
115228
+ session = this.sessionManager.getSession(request4.sessionId);
114838
115229
  if (!session) {
114839
- throw new Error(`Failed to auto-register session: ${request3.sessionId}`);
115230
+ throw new Error(`Failed to auto-register session: ${request4.sessionId}`);
114840
115231
  }
114841
115232
  }
114842
- if (request3.shownTabId !== void 0) {
114843
- if (request3.shownTabId && session.tabs.has(request3.shownTabId)) {
114844
- session.activeTabId = request3.shownTabId;
115233
+ if (request4.shownTabId !== void 0) {
115234
+ if (request4.shownTabId && session.tabs.has(request4.shownTabId)) {
115235
+ session.activeTabId = request4.shownTabId;
114845
115236
  } else {
114846
115237
  delete session.activeTabId;
114847
115238
  }
114848
115239
  }
114849
- const shouldCreateNewTab = request3.newTab !== false;
115240
+ const shouldCreateNewTab = request4.newTab !== false;
114850
115241
  const { tab, tabId, tabTitle } = this.resolveTab(
114851
115242
  session,
114852
- request3.tabId,
115243
+ request4.tabId,
114853
115244
  shouldCreateNewTab,
114854
- request3.title
115245
+ request4.title
114855
115246
  );
114856
115247
  if (!tab && !this.sessionManager.canAddTab(session.id) && !this.sessionManager.makeRoomForTab(session.id)) {
114857
115248
  throw new AppError(
@@ -115286,7 +115677,7 @@ var init_CredentialRequestService = __esm({
115286
115677
  }
115287
115678
  const id = import_crypto8.default.randomUUID();
115288
115679
  const token = import_crypto8.default.randomBytes(24).toString("base64url");
115289
- const request3 = {
115680
+ const request4 = {
115290
115681
  id,
115291
115682
  token,
115292
115683
  connectionId,
@@ -115297,26 +115688,26 @@ var init_CredentialRequestService = __esm({
115297
115688
  token
115298
115689
  )}`
115299
115690
  };
115300
- this.requests.set(id, request3);
115691
+ this.requests.set(id, request4);
115301
115692
  if (clientConsent !== void 0) {
115302
115693
  this.requestConsents.set(id, clientConsent);
115303
115694
  }
115304
- return request3;
115695
+ return request4;
115305
115696
  }
115306
115697
  get(id, token) {
115307
115698
  this.pruneExpired();
115308
- const request3 = this.requests.get(id);
115309
- if (!request3 || request3.token !== token) {
115699
+ const request4 = this.requests.get(id);
115700
+ if (!request4 || request4.token !== token) {
115310
115701
  return void 0;
115311
115702
  }
115312
- return request3;
115703
+ return request4;
115313
115704
  }
115314
115705
  async fulfill(id, token, password) {
115315
- const request3 = this.get(id, token);
115316
- if (!request3) {
115706
+ const request4 = this.get(id, token);
115707
+ if (!request4) {
115317
115708
  throw new Error("Credential request is invalid or expired.");
115318
115709
  }
115319
- if (request3.kind === "draft") {
115710
+ if (request4.kind === "draft") {
115320
115711
  throw new Error("This setup page needs an updated Grain.");
115321
115712
  }
115322
115713
  if (!password) {
@@ -115325,12 +115716,12 @@ var init_CredentialRequestService = __esm({
115325
115716
  return this.complete(id, token, { password });
115326
115717
  }
115327
115718
  async describe(id, token) {
115328
- const request3 = this.get(id, token);
115329
- if (!request3) {
115719
+ const request4 = this.get(id, token);
115720
+ if (!request4) {
115330
115721
  return void 0;
115331
115722
  }
115332
115723
  const profile = await this.connectionManager.getProfile(
115333
- request3.connectionId,
115724
+ request4.connectionId,
115334
115725
  this.requestConsents.get(id)
115335
115726
  );
115336
115727
  if (!profile) {
@@ -115343,29 +115734,29 @@ var init_CredentialRequestService = __esm({
115343
115734
  )
115344
115735
  );
115345
115736
  return {
115346
- kind: request3.kind,
115347
- connectionId: request3.connectionId,
115348
- connectionName: request3.connectionName,
115349
- expiresAt: request3.expiresAt,
115737
+ kind: request4.kind,
115738
+ connectionId: request4.connectionId,
115739
+ connectionName: request4.connectionName,
115740
+ expiresAt: request4.expiresAt,
115350
115741
  profile: safeProfile
115351
115742
  };
115352
115743
  }
115353
115744
  async complete(id, token, input) {
115354
- const request3 = this.get(id, token);
115355
- if (!request3) {
115745
+ const request4 = this.get(id, token);
115746
+ if (!request4) {
115356
115747
  throw new Error("Credential request is invalid or expired.");
115357
115748
  }
115358
115749
  const fields = input.fields ?? {};
115359
- if (request3.kind === "password" && Object.keys(fields).length > 0) {
115750
+ if (request4.kind === "password" && Object.keys(fields).length > 0) {
115360
115751
  throw new Error("Only a password can be changed with this setup link.");
115361
115752
  }
115362
- if (request3.kind === "password" && !input.password) {
115753
+ if (request4.kind === "password" && !input.password) {
115363
115754
  throw new Error("Password is required.");
115364
115755
  }
115365
115756
  const clientConsent = this.requestConsents.get(id);
115366
- const profile = await this.connectionManager.getProfile(request3.connectionId, clientConsent);
115757
+ const profile = await this.connectionManager.getProfile(request4.connectionId, clientConsent);
115367
115758
  if (!profile) {
115368
- throw new Error(`Connection profile '${request3.connectionId}' not found`);
115759
+ throw new Error(`Connection profile '${request4.connectionId}' not found`);
115369
115760
  }
115370
115761
  const schema = this.connectorRegistry?.getConnectorMetadata().find((item) => item.id === profile.type)?.configSchema;
115371
115762
  if (Object.keys(fields).some(
@@ -115380,7 +115771,7 @@ var init_CredentialRequestService = __esm({
115380
115771
  draft: false,
115381
115772
  ...input.password !== void 0 ? { password: input.password } : {}
115382
115773
  });
115383
- if (request3.kind === "draft") {
115774
+ if (request4.kind === "draft") {
115384
115775
  this.telemetry?.capture(
115385
115776
  "first_value_step",
115386
115777
  { step: "connection_saved", outcome: "success", state: "mcp_server" },
@@ -115388,7 +115779,7 @@ var init_CredentialRequestService = __esm({
115388
115779
  );
115389
115780
  }
115390
115781
  } catch (e2) {
115391
- if (request3.kind !== "draft") {
115782
+ if (request4.kind !== "draft") {
115392
115783
  throw e2;
115393
115784
  }
115394
115785
  this.telemetry?.capture(
@@ -115405,11 +115796,11 @@ var init_CredentialRequestService = __esm({
115405
115796
  }
115406
115797
  this.requests.delete(id);
115407
115798
  this.requestConsents.delete(id);
115408
- return request3;
115799
+ return request4;
115409
115800
  }
115410
115801
  pruneExpired(now = Date.now()) {
115411
- for (const [id, request3] of this.requests.entries()) {
115412
- if (request3.expiresAt <= now) {
115802
+ for (const [id, request4] of this.requests.entries()) {
115803
+ if (request4.expiresAt <= now) {
115413
115804
  this.requests.delete(id);
115414
115805
  this.requestConsents.delete(id);
115415
115806
  }
@@ -115457,9 +115848,9 @@ async function createConnectionDraft(deps, args, clientConsent) {
115457
115848
  type: connector.id,
115458
115849
  draft: true
115459
115850
  });
115460
- let request3;
115851
+ let request4;
115461
115852
  try {
115462
- request3 = await service.create(connectionId, {
115853
+ request4 = await service.create(connectionId, {
115463
115854
  expiresInMinutes: input.expiresInMinutes,
115464
115855
  clientConsent
115465
115856
  });
@@ -115467,18 +115858,18 @@ async function createConnectionDraft(deps, args, clientConsent) {
115467
115858
  await deps.connectionManager.deleteProfile(connectionId);
115468
115859
  throw error52;
115469
115860
  }
115470
- const browserOpened = await deps.openBrowser?.(request3.url) ?? false;
115861
+ const browserOpened = await deps.openBrowser?.(request4.url) ?? false;
115471
115862
  return {
115472
115863
  structuredContent: {
115473
115864
  connectionId,
115474
- url: request3.url,
115865
+ url: request4.url,
115475
115866
  browserOpened,
115476
- expiresAt: new Date(request3.expiresAt).toISOString()
115867
+ expiresAt: new Date(request4.expiresAt).toISOString()
115477
115868
  },
115478
115869
  content: [
115479
115870
  {
115480
115871
  type: "text",
115481
- text: `Draft connection '${name}' (id ${connectionId}) created. Setup page: ${request3.url} (expires ${new Date(request3.expiresAt).toISOString()}).`
115872
+ text: `Draft connection '${name}' (id ${connectionId}) created. Setup page: ${request4.url} (expires ${new Date(request4.expiresAt).toISOString()}).`
115482
115873
  }
115483
115874
  ]
115484
115875
  };
@@ -115568,74 +115959,6 @@ var init_authHeaders = __esm({
115568
115959
  }
115569
115960
  });
115570
115961
 
115571
- // src/server/policy/callPolicy.ts
115572
- function clientPolicyFromMeta(meta3) {
115573
- const asked = meta3?.[CLIENT_POLICY_META_KEY];
115574
- if (typeof asked !== "object" || asked === null)
115575
- return void 0;
115576
- const safeMode = asked.safeMode;
115577
- return typeof safeMode === "boolean" ? { safeMode } : {};
115578
- }
115579
- function resolveCallPolicy(serviceProfile, serviceSafeMode, requested) {
115580
- if (requested?.safeMode === void 0) {
115581
- return { profile: serviceProfile, declined: [] };
115582
- }
115583
- if (requested.safeMode) {
115584
- const tightened = { ...serviceProfile, forceSafeMode: true };
115585
- return { profile: composeToolProfiles(serviceProfile, tightened), declined: [] };
115586
- }
115587
- if (isSafeModeActive(serviceProfile, serviceSafeMode)) {
115588
- return { profile: serviceProfile, declined: [SAFE_MODE_DECLINED_MESSAGE] };
115589
- }
115590
- return { profile: serviceProfile, declined: [] };
115591
- }
115592
- function alphaToolEnabled(name, chartsEnabled, ledgerEnabled) {
115593
- if (CHART_TOOLS.includes(name))
115594
- return chartsEnabled;
115595
- if (LEDGER_TOOLS.includes(name))
115596
- return ledgerEnabled;
115597
- return true;
115598
- }
115599
- function admitToolCall(profile, name, featureEnabled) {
115600
- if (!toolNamesForProfile(profile).has(name) || !featureEnabled) {
115601
- throw new Error("Unknown tool");
115602
- }
115603
- return refuseIfNotPermitted(profile, name);
115604
- }
115605
- function refuseRestToolCall(profile, name) {
115606
- const tool = name;
115607
- if (!ALL_TOOLS.includes(tool)) {
115608
- return void 0;
115609
- }
115610
- if (!toolNamesForProfile(profile).has(name)) {
115611
- return toolRefusalResult(profile, tool);
115612
- }
115613
- return refuseIfNotPermitted(profile, name);
115614
- }
115615
- function withPolicyNotice(result, policy) {
115616
- if (policy.declined.length === 0)
115617
- return result;
115618
- const existing = result;
115619
- const notice = { type: "text", text: policy.declined.join(" ") };
115620
- return {
115621
- ...existing,
115622
- content: Array.isArray(existing.content) ? [...existing.content, notice] : [notice],
115623
- _meta: { ...existing._meta, [DECLINED_POLICY_META_KEY]: policy.declined }
115624
- };
115625
- }
115626
- var CLIENT_POLICY_META_KEY, DECLINED_POLICY_META_KEY, SAFE_MODE_DECLINED_MESSAGE, CHART_TOOLS, LEDGER_TOOLS;
115627
- var init_callPolicy = __esm({
115628
- "src/server/policy/callPolicy.ts"() {
115629
- "use strict";
115630
- init_toolProfiles();
115631
- CLIENT_POLICY_META_KEY = "sqlpreview/policy";
115632
- DECLINED_POLICY_META_KEY = "sqlpreview/policyDeclined";
115633
- SAFE_MODE_DECLINED_MESSAGE = "Declined this client's request to run with safe mode off: 'mcpSafeMode' is client-restrict-only, so an attaching client may only make it more restrictive than the service, never less. This call ran under safe mode; the override was declined, not lost.";
115634
- CHART_TOOLS = ["render_chart", "save_chart", "list_charts"];
115635
- LEDGER_TOOLS = ["ledger_stats", "verify_ledger"];
115636
- }
115637
- });
115638
-
115639
115962
  // src/server/tools/toolDefinitions.ts
115640
115963
  function projectToolForWire(def) {
115641
115964
  const { name, description, inputSchema, _meta } = def;
@@ -116185,52 +116508,52 @@ function pickActiveConnectionId(profiles, explicitId) {
116185
116508
  );
116186
116509
  return active?.id ?? profiles[0]?.id;
116187
116510
  }
116188
- function buildCredentialRequiredResult(request3, browserOpened) {
116189
- const expiresAt = new Date(request3.expiresAt).toISOString();
116511
+ function buildCredentialRequiredResult(request4, browserOpened) {
116512
+ const expiresAt = new Date(request4.expiresAt).toISOString();
116190
116513
  return {
116191
116514
  isError: true,
116192
116515
  content: [
116193
116516
  {
116194
116517
  type: "text",
116195
- text: browserOpened ? `I opened a one-time Grain password page for '${request3.connectionName}' in your browser. Enter the password there, not in chat.
116518
+ text: browserOpened ? `I opened a one-time Grain password page for '${request4.connectionName}' in your browser. Enter the password there, not in chat.
116196
116519
 
116197
- If it did not open: ${request3.url}
116520
+ If it did not open: ${request4.url}
116198
116521
 
116199
- The link expires at ${expiresAt}. After saving the password, retry the query.` : `Connection '${request3.connectionName}' needs a password before this query can run. Open this one-time Grain credential form and enter it there \u2014 do not paste the password into chat:
116522
+ The link expires at ${expiresAt}. After saving the password, retry the query.` : `Connection '${request4.connectionName}' needs a password before this query can run. Open this one-time Grain credential form and enter it there \u2014 do not paste the password into chat:
116200
116523
 
116201
- ${request3.url}
116524
+ ${request4.url}
116202
116525
 
116203
116526
  The link expires at ${expiresAt}. After saving the password, retry the query.`
116204
116527
  }
116205
116528
  ],
116206
116529
  structuredContent: {
116207
116530
  status: "credential_required",
116208
- connectionId: request3.connectionId,
116209
- connectionName: request3.connectionName,
116531
+ connectionId: request4.connectionId,
116532
+ connectionName: request4.connectionName,
116210
116533
  ...browserOpened === void 0 ? {} : { browserOpened },
116211
- credentialUrl: request3.url,
116534
+ credentialUrl: request4.url,
116212
116535
  expiresAt,
116213
116536
  errorKind: "auth",
116214
116537
  errorId: "credential_required"
116215
116538
  }
116216
116539
  };
116217
116540
  }
116218
- function buildSetupRequiredResult(request3, browserOpened) {
116219
- const expiresAt = new Date(request3.expiresAt).toISOString();
116541
+ function buildSetupRequiredResult(request4, browserOpened) {
116542
+ const expiresAt = new Date(request4.expiresAt).toISOString();
116220
116543
  return {
116221
116544
  isError: true,
116222
116545
  content: [
116223
116546
  {
116224
116547
  type: "text",
116225
- text: `Connection '${request3.connectionName}' (id ${request3.connectionId}) is a draft and has no credentials yet. Setup page: ${request3.url} (expires ${expiresAt}). Queries on this connection will work once setup is saved.`
116548
+ text: `Connection '${request4.connectionName}' (id ${request4.connectionId}) is a draft and has no credentials yet. Setup page: ${request4.url} (expires ${expiresAt}). Queries on this connection will work once setup is saved.`
116226
116549
  }
116227
116550
  ],
116228
116551
  structuredContent: {
116229
116552
  status: "setup_required",
116230
- connectionId: request3.connectionId,
116231
- connectionName: request3.connectionName,
116553
+ connectionId: request4.connectionId,
116554
+ connectionName: request4.connectionName,
116232
116555
  ...browserOpened === void 0 ? {} : { browserOpened },
116233
- setupUrl: request3.url,
116556
+ setupUrl: request4.url,
116234
116557
  expiresAt,
116235
116558
  errorKind: "config",
116236
116559
  errorId: "setup_required"
@@ -117116,18 +117439,18 @@ var init_SessionChartService = __esm({
117116
117439
  this.sessionManager = sessionManager;
117117
117440
  this.runtime = runtime;
117118
117441
  }
117119
- async execute(request3) {
117120
- const session = this.sessionManager.getSession(request3.sessionId);
117121
- const tab = session?.tabs.get(request3.tabId);
117442
+ async execute(request4) {
117443
+ const session = this.sessionManager.getSession(request4.sessionId);
117444
+ const tab = session?.tabs.get(request4.tabId);
117122
117445
  if (!tab) {
117123
117446
  throw new Error(
117124
- `Result tab '${request3.tabId}' was not found in session '${request3.sessionId}'.`
117447
+ `Result tab '${request4.tabId}' was not found in session '${request4.sessionId}'.`
117125
117448
  );
117126
117449
  }
117127
117450
  if (!tab.rows || !tab.columns) {
117128
- throw new Error(`Result tab '${request3.tabId}' has no completed result to chart.`);
117451
+ throw new Error(`Result tab '${request4.tabId}' has no completed result to chart.`);
117129
117452
  }
117130
- const validation = validateChartSpec(request3.spec);
117453
+ const validation = validateChartSpec(request4.spec);
117131
117454
  if (!validation.valid) {
117132
117455
  throw new Error(`Invalid chart spec: ${validation.errors.join("; ")}`);
117133
117456
  }
@@ -117136,7 +117459,7 @@ var init_SessionChartService = __esm({
117136
117459
  tab.columns,
117137
117460
  tab.rows,
117138
117461
  this.runtime,
117139
- request3.paramValues
117462
+ request4.paramValues
117140
117463
  );
117141
117464
  }
117142
117465
  };
@@ -197598,23 +197921,23 @@ ${query.sql}`).join("\n\n")
197598
197921
  if (!connectionId) {
197599
197922
  throw new Error("connectionId is required");
197600
197923
  }
197601
- const request3 = await service.create(connectionId, {
197924
+ const request4 = await service.create(connectionId, {
197602
197925
  expiresInMinutes: typedArgs?.expiresInMinutes,
197603
197926
  clientConsent
197604
197927
  });
197605
- const browserOpened = await this.options.openBrowser?.(request3.url) ?? false;
197928
+ const browserOpened = await this.options.openBrowser?.(request4.url) ?? false;
197606
197929
  return {
197607
197930
  structuredContent: {
197608
- connectionId: request3.connectionId,
197609
- connectionName: request3.connectionName,
197610
- url: request3.url,
197931
+ connectionId: request4.connectionId,
197932
+ connectionName: request4.connectionName,
197933
+ url: request4.url,
197611
197934
  browserOpened,
197612
- expiresAt: new Date(request3.expiresAt).toISOString()
197935
+ expiresAt: new Date(request4.expiresAt).toISOString()
197613
197936
  },
197614
197937
  content: [
197615
197938
  {
197616
197939
  type: "text",
197617
- text: `One-time Grain setup page for '${request3.connectionName}' (id ${request3.connectionId}): ${request3.url} (expires ${new Date(request3.expiresAt).toISOString()}). ${browserOpened ? "The page was opened in the browser." : "The page was not opened in the browser."} Connection setup takes effect once saved.`
197940
+ text: `One-time Grain setup page for '${request4.connectionName}' (id ${request4.connectionId}): ${request4.url} (expires ${new Date(request4.expiresAt).toISOString()}). ${browserOpened ? "The page was opened in the browser." : "The page was not opened in the browser."} Connection setup takes effect once saved.`
197618
197941
  }
197619
197942
  ]
197620
197943
  };
@@ -197966,9 +198289,9 @@ ${query.sql}`).join("\n\n")
197966
198289
  if (!connectionId) {
197967
198290
  return null;
197968
198291
  }
197969
- const request3 = await service.create(connectionId, { clientConsent });
197970
- const browserOpened = await this.options.openBrowser?.(request3.url) ?? false;
197971
- return buildCredentialRequiredResult(request3, browserOpened);
198292
+ const request4 = await service.create(connectionId, { clientConsent });
198293
+ const browserOpened = await this.options.openBrowser?.(request4.url) ?? false;
198294
+ return buildCredentialRequiredResult(request4, browserOpened);
197972
198295
  } catch (err) {
197973
198296
  logger.warn("[MCP] Failed to build credential_required result", err);
197974
198297
  return null;
@@ -197983,9 +198306,9 @@ ${query.sql}`).join("\n\n")
197983
198306
  const profile = profiles.find((item) => item.id === connectionId);
197984
198307
  if (!profile?.draft)
197985
198308
  return null;
197986
- const request3 = await service.create(profile.id, { clientConsent });
197987
- const browserOpened = await this.options.openBrowser?.(request3.url) ?? false;
197988
- return buildSetupRequiredResult(request3, browserOpened);
198309
+ const request4 = await service.create(profile.id, { clientConsent });
198310
+ const browserOpened = await this.options.openBrowser?.(request4.url) ?? false;
198311
+ return buildSetupRequiredResult(request4, browserOpened);
197989
198312
  }
197990
198313
  async chartDocuments(root) {
197991
198314
  if (!this.chartsEnabled) {
@@ -206512,8 +206835,8 @@ function registerConnectionSetupRoutes(app, context2) {
206512
206835
  app.get("/connection-setup/:id", (req, res) => {
206513
206836
  setCredentialPageHeaders(res);
206514
206837
  const token = typeof req.query["token"] === "string" ? req.query["token"] : "";
206515
- const request3 = req.params.id ? context2.credentialRequestService.get(req.params.id, token) : void 0;
206516
- if (!request3) {
206838
+ const request4 = req.params.id ? context2.credentialRequestService.get(req.params.id, token) : void 0;
206839
+ if (!request4) {
206517
206840
  res.status(404).send(renderCredentialPage({ error: "This credential request is invalid or expired." }));
206518
206841
  return;
206519
206842
  }
@@ -206545,11 +206868,11 @@ function registerConnectionSetupRoutes(app, context2) {
206545
206868
  res.type("html").send(bundle);
206546
206869
  return;
206547
206870
  }
206548
- if (request3.kind === "draft") {
206871
+ if (request4.kind === "draft") {
206549
206872
  res.send(renderCredentialPage({ error: "This setup page needs an updated Grain." }));
206550
206873
  return;
206551
206874
  }
206552
- res.send(renderCredentialPage({ request: request3 }));
206875
+ res.send(renderCredentialPage({ request: request4 }));
206553
206876
  });
206554
206877
  app.get("/connection-setup/:id/state", async (req, res) => {
206555
206878
  setCredentialPageHeaders(res);
@@ -206736,11 +207059,11 @@ var init_ClientIdentity = __esm({
206736
207059
  });
206737
207060
 
206738
207061
  // src/server/auth/requireDaemonAuth.ts
206739
- function setRequestClient(request3, identity2) {
206740
- requestClients.set(request3, identity2);
207062
+ function setRequestClient(request4, identity2) {
207063
+ requestClients.set(request4, identity2);
206741
207064
  }
206742
- function getRequestClient(request3) {
206743
- return requestClients.get(request3);
207065
+ function getRequestClient(request4) {
207066
+ return requestClients.get(request4);
206744
207067
  }
206745
207068
  function isPublicDaemonPath(pathname) {
206746
207069
  if (PUBLIC_EXACT_PATHS.has(pathname)) {
@@ -206909,6 +207232,7 @@ function createSettingsUpdateHandler(context2) {
206909
207232
  maxRowsToDisplay: context2.resolvedConfig.config.query.maxRows,
206910
207233
  mcpSafeMode: context2.resolvedConfig.config.mcp.safeMode,
206911
207234
  confirmWriteQueries: context2.toolManager.isConfirmWrites,
207235
+ resultsCardRouting: context2.toolManager.isResultsCardRoutingEnabled,
206912
207236
  ...declined.length > 0 ? { declined } : {}
206913
207237
  });
206914
207238
  } catch (err) {
@@ -207115,14 +207439,14 @@ function registerDaemonHttpRoutes(context2, mcpHttpSurface) {
207115
207439
  setCredentialPageHeaders(res);
207116
207440
  const id = req.params.id;
207117
207441
  const token = typeof req.query["token"] === "string" ? req.query["token"] : "";
207118
- const request3 = id ? context2.credentialRequestService.get(id, token) : void 0;
207119
- if (!request3) {
207442
+ const request4 = id ? context2.credentialRequestService.get(id, token) : void 0;
207443
+ if (!request4) {
207120
207444
  res.status(404).send(renderCredentialPage({ error: "This credential request is invalid or expired." }));
207121
207445
  return;
207122
207446
  }
207123
207447
  res.redirect(
207124
207448
  302,
207125
- `/connection-setup/${encodeURIComponent(request3.id)}?token=${encodeURIComponent(token)}`
207449
+ `/connection-setup/${encodeURIComponent(request4.id)}?token=${encodeURIComponent(token)}`
207126
207450
  );
207127
207451
  });
207128
207452
  registerConnectionSetupRoutes(app, context2);
@@ -207250,8 +207574,10 @@ data: ${Date.now()}
207250
207574
  app.get("/api/v1/update", (_req, res) => {
207251
207575
  res.json(updateService.status());
207252
207576
  });
207253
- app.post("/api/v1/update/restart", async (_req, res) => {
207254
- const result = await updateService.restartToUpdate();
207577
+ app.post("/api/v1/update/restart", import_express2.default.json(), async (req, res) => {
207578
+ const result = await updateService.restartToUpdate({
207579
+ discardResults: req.body?.discardResults === true
207580
+ });
207255
207581
  res.json({ result, blockers: updateService.status().blockers });
207256
207582
  });
207257
207583
  }
@@ -207716,11 +208042,11 @@ function readCredentialTemplate() {
207716
208042
  }
207717
208043
  }
207718
208044
  function credentialBody(input) {
207719
- const request3 = input.request;
208045
+ const request4 = input.request;
207720
208046
  const status = input.success ? `<p class="grain-connection-success" role="status">${escapeHtml(input.success)}</p>` : input.error ? `<p class="grain-connection-error" role="alert">${escapeHtml(input.error)}</p>` : "";
207721
- const form = request3 ? `<p class="grain-connection-intro">Enter the password for <strong>${escapeHtml(request3.connectionName)}</strong>${input.connectionType ? ` <span class="grain-credential-meta">(${escapeHtml(input.connectionType)})</span>` : ""}.</p>
207722
- <form method="post" action="/credential-requests/${encodeURIComponent(request3.id)}" autocomplete="off" class="grain-connection-section">
207723
- <input type="hidden" name="token" value="${escapeHtml(request3.token)}" />
208047
+ const form = request4 ? `<p class="grain-connection-intro">Enter the password for <strong>${escapeHtml(request4.connectionName)}</strong>${input.connectionType ? ` <span class="grain-credential-meta">(${escapeHtml(input.connectionType)})</span>` : ""}.</p>
208048
+ <form method="post" action="/credential-requests/${encodeURIComponent(request4.id)}" autocomplete="off" class="grain-connection-section">
208049
+ <input type="hidden" name="token" value="${escapeHtml(request4.token)}" />
207724
208050
  <div class="grain-connection-field">
207725
208051
  <label for="password">Password</label>
207726
208052
  <input id="password" class="grain-connection-password" name="password" type="password" autocomplete="new-password" data-1p-ignore data-lpignore="true" autofocus required />
@@ -207730,7 +208056,7 @@ function credentialBody(input) {
207730
208056
  </div>
207731
208057
  </form>
207732
208058
  <p class="grain-credential-meta">Your password goes straight to Grain on this computer. Your agent never sees it. This link works once and expires at ${escapeHtml(
207733
- new Date(request3.expiresAt).toLocaleString()
208059
+ new Date(request4.expiresAt).toLocaleString()
207734
208060
  )}.</p>` : "";
207735
208061
  return `<main class="grain-connection-page"><div class="grain-credential-card"><h1>Connection password</h1>${status}${form}</div></main>`;
207736
208062
  }
@@ -207741,16 +208067,16 @@ function renderCredentialPage(input, template = readCredentialTemplate()) {
207741
208067
  const title = "Grain Credential Request";
207742
208068
  const message = input.success || input.error || "";
207743
208069
  const escapedMessage = escapeHtml(message);
207744
- const request3 = input.request;
207745
- const form = request3 ? `<p>Enter the password for <strong>${escapeHtml(request3.connectionName)}</strong>.</p>
208070
+ const request4 = input.request;
208071
+ const form = request4 ? `<p>Enter the password for <strong>${escapeHtml(request4.connectionName)}</strong>.</p>
207746
208072
  <p class="hint">The password is sent directly to the local Grain daemon and is not shown in the MCP/chat transcript.</p>
207747
- <form method="post" action="/credential-requests/${encodeURIComponent(request3.id)}" autocomplete="off">
207748
- <input type="hidden" name="token" value="${escapeHtml(request3.token)}" />
208073
+ <form method="post" action="/credential-requests/${encodeURIComponent(request4.id)}" autocomplete="off">
208074
+ <input type="hidden" name="token" value="${escapeHtml(request4.token)}" />
207749
208075
  <label for="password">Password</label>
207750
208076
  <input id="password" name="password" type="password" autocomplete="new-password" data-1p-ignore data-lpignore="true" autofocus required />
207751
208077
  <button type="submit">Save password</button>
207752
208078
  </form>
207753
- <p class="hint">This request expires at ${escapeHtml(new Date(request3.expiresAt).toLocaleString())}.</p>` : "";
208079
+ <p class="hint">This request expires at ${escapeHtml(new Date(request4.expiresAt).toLocaleString())}.</p>` : "";
207754
208080
  return `<!doctype html>
207755
208081
  <html lang="en">
207756
208082
  <head>
@@ -209432,8 +209758,8 @@ var init_server = __esm({
209432
209758
  *
209433
209759
  * @experimental
209434
209760
  */
209435
- requestStream(request3, resultSchema, options) {
209436
- return this._server.requestStream(request3, resultSchema, options);
209761
+ requestStream(request4, resultSchema, options) {
209762
+ return this._server.requestStream(request4, resultSchema, options);
209437
209763
  }
209438
209764
  /**
209439
209765
  * Sends a sampling request and returns an AsyncGenerator that yields response messages.
@@ -209654,12 +209980,12 @@ var init_server2 = __esm({
209654
209980
  this._capabilities = options?.capabilities ?? {};
209655
209981
  this._instructions = options?.instructions;
209656
209982
  this._jsonSchemaValidator = options?.jsonSchemaValidator ?? new AjvJsonSchemaValidator();
209657
- this.setRequestHandler(InitializeRequestSchema, (request3) => this._oninitialize(request3));
209983
+ this.setRequestHandler(InitializeRequestSchema, (request4) => this._oninitialize(request4));
209658
209984
  this.setNotificationHandler(InitializedNotificationSchema, () => this.oninitialized?.());
209659
209985
  if (this._capabilities.logging) {
209660
- this.setRequestHandler(SetLevelRequestSchema, async (request3, extra) => {
209986
+ this.setRequestHandler(SetLevelRequestSchema, async (request4, extra) => {
209661
209987
  const transportSessionId = extra.sessionId || extra.requestInfo?.headers["mcp-session-id"] || void 0;
209662
- const { level } = request3.params;
209988
+ const { level } = request4.params;
209663
209989
  const parseResult = LoggingLevelSchema.safeParse(level);
209664
209990
  if (parseResult.success) {
209665
209991
  this._loggingLevels.set(transportSessionId, parseResult.data);
@@ -209709,14 +210035,14 @@ var init_server2 = __esm({
209709
210035
  }
209710
210036
  const method = methodValue;
209711
210037
  if (method === "tools/call") {
209712
- const wrappedHandler = async (request3, extra) => {
209713
- const validatedRequest = safeParse3(CallToolRequestSchema, request3);
210038
+ const wrappedHandler = async (request4, extra) => {
210039
+ const validatedRequest = safeParse3(CallToolRequestSchema, request4);
209714
210040
  if (!validatedRequest.success) {
209715
210041
  const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
209716
210042
  throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage}`);
209717
210043
  }
209718
210044
  const { params } = validatedRequest.data;
209719
- const result = await Promise.resolve(handler(request3, extra));
210045
+ const result = await Promise.resolve(handler(request4, extra));
209720
210046
  if (params.task) {
209721
210047
  const taskValidationResult = safeParse3(CreateTaskResultSchema, result);
209722
210048
  if (!taskValidationResult.success) {
@@ -209847,10 +210173,10 @@ var init_server2 = __esm({
209847
210173
  }
209848
210174
  assertToolsCallTaskCapability(this._capabilities.tasks?.requests, method, "Server");
209849
210175
  }
209850
- async _oninitialize(request3) {
209851
- const requestedVersion = request3.params.protocolVersion;
209852
- this._clientCapabilities = request3.params.capabilities;
209853
- this._clientVersion = request3.params.clientInfo;
210176
+ async _oninitialize(request4) {
210177
+ const requestedVersion = request4.params.protocolVersion;
210178
+ this._clientCapabilities = request4.params.capabilities;
210179
+ this._clientVersion = request4.params.clientInfo;
209854
210180
  const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.includes(requestedVersion) ? requestedVersion : LATEST_PROTOCOL_VERSION;
209855
210181
  return {
209856
210182
  protocolVersion,
@@ -228095,12 +228421,12 @@ var require_service = __commonJS({
228095
228421
  this.requestDelimited = Boolean(requestDelimited);
228096
228422
  this.responseDelimited = Boolean(responseDelimited);
228097
228423
  }
228098
- Service.prototype.rpcCall = function rpcCall(method, requestCtor, responseCtor, request3, callback) {
228099
- if (!request3)
228424
+ Service.prototype.rpcCall = function rpcCall(method, requestCtor, responseCtor, request4, callback) {
228425
+ if (!request4)
228100
228426
  throw TypeError("request must be specified");
228101
228427
  var self2 = this;
228102
228428
  if (!callback)
228103
- return util3.asPromise(rpcCall, self2, method, requestCtor, responseCtor, request3);
228429
+ return util3.asPromise(rpcCall, self2, method, requestCtor, responseCtor, request4);
228104
228430
  if (!self2.rpcImpl) {
228105
228431
  setTimeout(function() {
228106
228432
  callback(Error("already ended"));
@@ -228110,7 +228436,7 @@ var require_service = __commonJS({
228110
228436
  try {
228111
228437
  return self2.rpcImpl(
228112
228438
  method,
228113
- requestCtor[self2.requestDelimited ? "encodeDelimited" : "encode"](request3).finish(),
228439
+ requestCtor[self2.requestDelimited ? "encodeDelimited" : "encode"](request4).finish(),
228114
228440
  function rpcCallback(err, response) {
228115
228441
  if (err) {
228116
228442
  self2.emit("error", err, method);
@@ -232816,8 +233142,8 @@ var require_root = __commonJS({
232816
233142
  MetricsService.create = function create5(rpcImpl, requestDelimited, responseDelimited) {
232817
233143
  return new this(rpcImpl, requestDelimited, responseDelimited);
232818
233144
  };
232819
- Object.defineProperty(MetricsService.prototype["export"] = function export_(request3, callback) {
232820
- return this.rpcCall(export_, $root.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest, $root.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse, request3, callback);
233145
+ Object.defineProperty(MetricsService.prototype["export"] = function export_(request4, callback) {
233146
+ return this.rpcCall(export_, $root.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest, $root.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceResponse, request4, callback);
232821
233147
  }, "name", { value: "Export" });
232822
233148
  return MetricsService;
232823
233149
  }();
@@ -233461,8 +233787,8 @@ var require_metrics = __commonJS({
233461
233787
  var metricsRequestType = root.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest;
233462
233788
  exports.ProtobufMetricsSerializer = {
233463
233789
  serializeRequest: (arg) => {
233464
- const request3 = (0, internal_1.createExportMetricsServiceRequest)([arg], utils_1.PROTOBUF_ENCODER);
233465
- return metricsRequestType.encode(request3).finish();
233790
+ const request4 = (0, internal_1.createExportMetricsServiceRequest)([arg], utils_1.PROTOBUF_ENCODER);
233791
+ return metricsRequestType.encode(request4).finish();
233466
233792
  },
233467
233793
  deserializeResponse: (arg) => {
233468
233794
  return metricsResponseType.decode(arg);
@@ -233868,9 +234194,9 @@ var require_logs3 = __commonJS({
233868
234194
  var api_1 = (init_esm2(), __toCommonJS(esm_exports));
233869
234195
  exports.JsonLogsSerializer = {
233870
234196
  serializeRequest: (arg) => {
233871
- const request3 = (0, internal_1.createExportLogsServiceRequest)(arg, utils_1.JSON_ENCODER);
234197
+ const request4 = (0, internal_1.createExportLogsServiceRequest)(arg, utils_1.JSON_ENCODER);
233872
234198
  const encoder = new TextEncoder();
233873
- return encoder.encode(JSON.stringify(request3));
234199
+ return encoder.encode(JSON.stringify(request4));
233874
234200
  },
233875
234201
  deserializeResponse: (arg) => {
233876
234202
  if (arg.length === 0) {
@@ -233912,9 +234238,9 @@ var require_metrics2 = __commonJS({
233912
234238
  var api_1 = (init_esm2(), __toCommonJS(esm_exports));
233913
234239
  exports.JsonMetricsSerializer = {
233914
234240
  serializeRequest: (arg) => {
233915
- const request3 = (0, internal_1.createExportMetricsServiceRequest)([arg], utils_1.JSON_ENCODER);
234241
+ const request4 = (0, internal_1.createExportMetricsServiceRequest)([arg], utils_1.JSON_ENCODER);
233916
234242
  const encoder = new TextEncoder();
233917
- return encoder.encode(JSON.stringify(request3));
234243
+ return encoder.encode(JSON.stringify(request4));
233918
234244
  },
233919
234245
  deserializeResponse: (arg) => {
233920
234246
  if (arg.length === 0) {
@@ -234081,9 +234407,9 @@ var require_trace2 = __commonJS({
234081
234407
  var api_1 = (init_esm2(), __toCommonJS(esm_exports));
234082
234408
  exports.JsonTraceSerializer = {
234083
234409
  serializeRequest: (arg) => {
234084
- const request3 = (0, internal_1.createExportTraceServiceRequest)(arg, utils_1.JSON_ENCODER);
234410
+ const request4 = (0, internal_1.createExportTraceServiceRequest)(arg, utils_1.JSON_ENCODER);
234085
234411
  const encoder = new TextEncoder();
234086
- return encoder.encode(JSON.stringify(request3));
234412
+ return encoder.encode(JSON.stringify(request4));
234087
234413
  },
234088
234414
  deserializeResponse: (arg) => {
234089
234415
  if (arg.length === 0) {
@@ -234277,7 +234603,7 @@ var init_version3 = __esm({
234277
234603
  });
234278
234604
 
234279
234605
  // node_modules/@opentelemetry/otlp-exporter-base/build/esm/transport/http-transport-utils.js
234280
- function sendWithHttp(request3, url3, headers, compression, userAgent, agent, data, timeoutMillis) {
234606
+ function sendWithHttp(request4, url3, headers, compression, userAgent, agent, data, timeoutMillis) {
234281
234607
  return new Promise((resolve15) => {
234282
234608
  const parsedUrl = new URL(url3);
234283
234609
  if (userAgent) {
@@ -234293,7 +234619,7 @@ function sendWithHttp(request3, url3, headers, compression, userAgent, agent, da
234293
234619
  headers,
234294
234620
  agent
234295
234621
  };
234296
- const req = request3(options, (res) => {
234622
+ const req = request4(options, (res) => {
234297
234623
  const responseData = [];
234298
234624
  let responseSize = 0;
234299
234625
  res.on("data", (chunk) => {
@@ -234418,8 +234744,8 @@ var init_http_transport_utils = __esm({
234418
234744
  // node_modules/@opentelemetry/otlp-exporter-base/build/esm/transport/http-exporter-transport.js
234419
234745
  async function requestFunctionFactory(protocol) {
234420
234746
  const module2 = protocol === "http:" ? import("http") : import("https");
234421
- const { request: request3 } = await module2;
234422
- return request3;
234747
+ const { request: request4 } = await module2;
234748
+ return request4;
234423
234749
  }
234424
234750
  function createHttpExporterTransport(parameters) {
234425
234751
  return new HttpExporterTransport(parameters);
@@ -234435,9 +234761,9 @@ var init_http_exporter_transport = __esm({
234435
234761
  this._parameters = parameters;
234436
234762
  }
234437
234763
  async send(data, timeoutMillis) {
234438
- const { agent, request: request3 } = await this._loadUtils();
234764
+ const { agent, request: request4 } = await this._loadUtils();
234439
234765
  const headers = await this._parameters.headers();
234440
- return sendWithHttp(request3, this._parameters.url, headers, this._parameters.compression, this._parameters.userAgent, agent, data, timeoutMillis);
234766
+ return sendWithHttp(request4, this._parameters.url, headers, this._parameters.compression, this._parameters.userAgent, agent, data, timeoutMillis);
234441
234767
  }
234442
234768
  shutdown() {
234443
234769
  }
@@ -234445,11 +234771,11 @@ var init_http_exporter_transport = __esm({
234445
234771
  let utils = this._utils;
234446
234772
  if (utils === null) {
234447
234773
  const protocol = new URL(this._parameters.url).protocol;
234448
- const [agent, request3] = await Promise.all([
234774
+ const [agent, request4] = await Promise.all([
234449
234775
  this._parameters.agentFactory(protocol),
234450
234776
  requestFunctionFactory(protocol)
234451
234777
  ]);
234452
- utils = this._utils = { agent, request: request3 };
234778
+ utils = this._utils = { agent, request: request4 };
234453
234779
  }
234454
234780
  return utils;
234455
234781
  }
@@ -235224,11 +235550,11 @@ var require_PrometheusExporter = __commonJS({
235224
235550
  * @param request Incoming HTTP request to export server
235225
235551
  * @param response HTTP response object used to respond to request
235226
235552
  */
235227
- _requestHandler = (request3, response) => {
235553
+ _requestHandler = (request4, response) => {
235228
235554
  let pathname;
235229
235555
  try {
235230
- if (request3.url != null) {
235231
- pathname = new url_1.URL(request3.url, this._baseUrl).pathname;
235556
+ if (request4.url != null) {
235557
+ pathname = new url_1.URL(request4.url, this._baseUrl).pathname;
235232
235558
  }
235233
235559
  } catch {
235234
235560
  response.statusCode = 400;
@@ -235423,7 +235749,7 @@ var require_util3 = __commonJS({
235423
235749
  exports.prepareSend = void 0;
235424
235750
  var api_1 = (init_esm2(), __toCommonJS(esm_exports));
235425
235751
  var core_1 = require_src2();
235426
- var http10 = require("http");
235752
+ var http11 = require("http");
235427
235753
  var https6 = require("https");
235428
235754
  function prepareSend(urlStr, headers) {
235429
235755
  const url3 = new URL(urlStr);
@@ -235439,8 +235765,8 @@ var require_util3 = __commonJS({
235439
235765
  api_1.diag.debug("Zipkin send with empty spans");
235440
235766
  return done({ code: core_1.ExportResultCode.SUCCESS });
235441
235767
  }
235442
- const { request: request3 } = url3.protocol === "http:" ? http10 : https6;
235443
- const req = request3(url3, reqOpts, (res) => {
235768
+ const { request: request4 } = url3.protocol === "http:" ? http11 : https6;
235769
+ const req = request4(url3, reqOpts, (res) => {
235444
235770
  let rawData = "";
235445
235771
  res.on("data", (chunk) => {
235446
235772
  rawData += chunk;
@@ -237990,7 +238316,6 @@ var init_ResultRouting = __esm({
237990
238316
  ResultRouting = class {
237991
238317
  constructor(options) {
237992
238318
  this.options = options;
237993
- this.firstResultRevealed = false;
237994
238319
  }
237995
238320
  async apply(name, result, enabled, rendersApps, origin2, clientLabel, clientConsent) {
237996
238321
  const isQuery = name === "run_query";
@@ -238021,8 +238346,8 @@ var init_ResultRouting = __esm({
238021
238346
  }
238022
238347
  }
238023
238348
  }
238024
- if (enabled && isQuery && !this.firstResultRevealed && structured?.["status"] === "success" && typeof structured["sessionId"] === "string" && typeof structured["tabId"] === "string" && await editorConfirmation.reveal(roots2, structured["sessionId"], structured["tabId"])) {
238025
- this.firstResultRevealed = true;
238349
+ if (enabled && isQuery && structured?.["status"] === "success" && typeof structured["sessionId"] === "string" && typeof structured["tabId"] === "string") {
238350
+ await editorConfirmation.reveal(roots2, structured["sessionId"], structured["tabId"]);
238026
238351
  }
238027
238352
  if ((route === "text-workspace" || route === "text-editor") && isQuery && structured?.["status"] === "success") {
238028
238353
  const sessionId = structured["sessionId"];
@@ -238195,11 +238520,13 @@ var init_DaemonMcpServer = __esm({
238195
238520
  * to observe. An `unknown` label is always preferable to a failed read.
238196
238521
  */
238197
238522
  resolveClientLabel() {
238523
+ return normalizeTelemetryMcpClient(this.resolveClientName());
238524
+ }
238525
+ resolveClientName() {
238198
238526
  try {
238199
- const reported = typeof this.server.getClientVersion === "function" ? this.server.getClientVersion()?.name : void 0;
238200
- return normalizeTelemetryMcpClient(reported);
238527
+ return (typeof this.server.getClientVersion === "function" ? this.server.getClientVersion()?.name : void 0)?.trim();
238201
238528
  } catch {
238202
- return "unknown";
238529
+ return void 0;
238203
238530
  }
238204
238531
  }
238205
238532
  clientRendersApps() {
@@ -238269,13 +238596,13 @@ var init_DaemonMcpServer = __esm({
238269
238596
  tools: this.toolsForClient()
238270
238597
  };
238271
238598
  });
238272
- this.server.setRequestHandler(CallToolRequestSchema, async (request3) => {
238599
+ this.server.setRequestHandler(CallToolRequestSchema, async (request4) => {
238273
238600
  return await getTracer().startActiveSpan(`mcp.tool_call`, async (span) => {
238274
238601
  try {
238275
- span.setAttribute("mcp.tool.name", request3.params.name);
238276
- if (request3.params.name === "open_result_view") {
238602
+ span.setAttribute("mcp.tool.name", request4.params.name);
238603
+ if (request4.params.name === "open_result_view") {
238277
238604
  return handleOpenResultView({
238278
- args: request3.params.arguments,
238605
+ args: request4.params.arguments,
238279
238606
  enabled: this.toolManager.isResultsCardRoutingEnabled,
238280
238607
  clientRendersApps: this.clientRendersApps(),
238281
238608
  toolRegistered: this.toolManager.getTools(this.profile).some((tool) => tool.name === "open_result_view"),
@@ -238289,9 +238616,12 @@ var init_DaemonMcpServer = __esm({
238289
238616
  });
238290
238617
  }
238291
238618
  const clientLabel = this.resolveClientLabel();
238619
+ const args = request4.params.arguments;
238620
+ const clientName = this.resolveClientName();
238621
+ const toolArgs = request4.params.name === "run_query" && args && !args["displayName"] && clientName ? { ...args, displayName: clientName } : args;
238292
238622
  const result = await this.toolManager.handleToolCall(
238293
- request3.params.name,
238294
- request3.params.arguments,
238623
+ request4.params.name,
238624
+ toolArgs,
238295
238625
  this.origin,
238296
238626
  clientLabel,
238297
238627
  this.profile,
@@ -238302,13 +238632,13 @@ var init_DaemonMcpServer = __esm({
238302
238632
  // the second attached client the first one's policy. It can only ever
238303
238633
  // tighten; `resolveCallPolicy` declines anything that would relax a
238304
238634
  // control the service set, and says so on the result.
238305
- clientPolicyFromMeta(request3.params._meta),
238635
+ clientPolicyFromMeta(request4.params._meta),
238306
238636
  this.telemetryConsent
238307
238637
  );
238308
238638
  const rendersApps = this.clientRendersApps();
238309
238639
  const routingEnabled = Boolean(this.toolManager.isResultsCardRoutingEnabled);
238310
238640
  await this.resultRouting.apply(
238311
- request3.params.name,
238641
+ request4.params.name,
238312
238642
  result,
238313
238643
  routingEnabled,
238314
238644
  rendersApps,
@@ -238403,8 +238733,8 @@ var init_DaemonMcpServer = __esm({
238403
238733
  });
238404
238734
  return { resources };
238405
238735
  });
238406
- this.server.setRequestHandler(ReadResourceRequestSchema, async (request3) => {
238407
- const uri = request3.params.uri;
238736
+ this.server.setRequestHandler(ReadResourceRequestSchema, async (request4) => {
238737
+ const uri = request4.params.uri;
238408
238738
  const clientLabel = this.resolveClientLabel();
238409
238739
  const routingEnabled = Boolean(this.toolManager.isResultsCardRoutingEnabled);
238410
238740
  if (uri === UI_FULL_RESOURCE_URI && !routingEnabled) {
@@ -238990,8 +239320,8 @@ var init_DaemonSocketSurface = __esm({
238990
239320
  });
238991
239321
  let isRegistered = false;
238992
239322
  if (typeof server.setRequestHandler === "function") {
238993
- server.setRequestHandler(EditorWindowStateRequestSchema, async (request3) => {
238994
- editorConfirmation.report(server, request3.params.folders, request3.params.focused);
239323
+ server.setRequestHandler(EditorWindowStateRequestSchema, async (request4) => {
239324
+ editorConfirmation.report(server, request4.params.folders, request4.params.focused);
238995
239325
  return { ok: true };
238996
239326
  });
238997
239327
  }
@@ -255656,7 +255986,7 @@ var init_ActivationGate = __esm({
255656
255986
  throw error52;
255657
255987
  }
255658
255988
  }
255659
- async tryActivate(activate) {
255989
+ async tryActivate(activate, options = {}) {
255660
255990
  if (this.admission.isDraining || this.activationInProgress) {
255661
255991
  return "blocked";
255662
255992
  }
@@ -255664,7 +255994,9 @@ var init_ActivationGate = __esm({
255664
255994
  this.activationInProgress = true;
255665
255995
  try {
255666
255996
  this.options.onAdmissionClosed?.();
255667
- if (this.admission.otherInFlightCount > 0 || !this.isIdle()) {
255997
+ const state = this.options.inspect();
255998
+ const activationState = options.discardResults ? { ...state, retainedResultTabs: 0 } : state;
255999
+ if (this.admission.otherInFlightCount > 0 || !isIdleState(activationState)) {
255668
256000
  this.reopenAdmission();
255669
256001
  return "blocked";
255670
256002
  }
@@ -255937,14 +256269,18 @@ var init_UpdateService = __esm({
255937
256269
  lastError: this.lastError
255938
256270
  };
255939
256271
  }
255940
- async restartToUpdate() {
255941
- const stagedVersion = this.stager.stagedVersion();
255942
- if (stagedVersion === null) {
256272
+ async restartToUpdate(options = {}) {
256273
+ const stagedVersion2 = this.stager.stagedVersion();
256274
+ if (stagedVersion2 === null) {
255943
256275
  return "blocked";
255944
256276
  }
255945
256277
  try {
255946
- if (this.requestUpdate) {
255947
- return await this.activationGate.tryActivate(() => this.requestUpdate("client_request"));
256278
+ const requestUpdate = this.requestUpdate;
256279
+ if (requestUpdate) {
256280
+ return await this.activationGate.tryActivate(
256281
+ () => requestUpdate("client_request"),
256282
+ options
256283
+ );
255948
256284
  }
255949
256285
  } catch (error52) {
255950
256286
  this.lastError = error52 instanceof Error ? error52.message : String(error52);
@@ -255963,8 +256299,8 @@ var init_UpdateService = __esm({
255963
256299
  const manifest = parseReleaseManifest(rawManifest);
255964
256300
  this.lastCheckedAt = this.now().toISOString();
255965
256301
  this.lastError = null;
255966
- const stagedVersion = this.stager.stagedVersion();
255967
- if (stagedVersion !== null) {
256302
+ const stagedVersion2 = this.stager.stagedVersion();
256303
+ if (stagedVersion2 !== null) {
255968
256304
  return "staged";
255969
256305
  }
255970
256306
  if (!isUpgrade(manifest, this.currentVersion)) {
@@ -256019,6 +256355,11 @@ function pruneOldVersions(configHome, keep) {
256019
256355
  if (keep.running) {
256020
256356
  protectedVersions.add(keep.running);
256021
256357
  }
256358
+ if (keep.protect) {
256359
+ for (const version3 of keep.protect) {
256360
+ protectedVersions.add(version3);
256361
+ }
256362
+ }
256022
256363
  const extra = Number.isFinite(keep.extra) ? Math.max(0, Math.floor(keep.extra)) : 0;
256023
256364
  const candidates = retainedApplicationVersions(configHome).filter(isVersion).filter((version3) => !protectedVersions.has(version3));
256024
256365
  const removed = [];
@@ -256044,6 +256385,13 @@ var init_VersionRetention = __esm({
256044
256385
  });
256045
256386
 
256046
256387
  // src/server/update/UpdateStager.ts
256388
+ function replayObserver(callback) {
256389
+ try {
256390
+ callback();
256391
+ } catch {
256392
+ return;
256393
+ }
256394
+ }
256047
256395
  function isWithin3(parent, child) {
256048
256396
  const relative9 = path55.relative(path55.resolve(parent), path55.resolve(child));
256049
256397
  return relative9 === "" || !relative9.startsWith(`..${path55.sep}`) && relative9 !== "..";
@@ -256134,6 +256482,8 @@ var init_UpdateStager = __esm({
256134
256482
  SEMVER_PATTERN3 = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-(?:0|[1-9]\d*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|[0-9A-Za-z-]*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
256135
256483
  UpdateStager = class {
256136
256484
  constructor(options) {
256485
+ this.stagedInProcess = /* @__PURE__ */ new Set();
256486
+ this.inFlight = null;
256137
256487
  this.configHome = options.configHome;
256138
256488
  this.currentVersion = options.currentVersion;
256139
256489
  this.downloadDir = options.downloadDir ?? os9.tmpdir();
@@ -256185,6 +256535,59 @@ var init_UpdateStager = __esm({
256185
256535
  return highest;
256186
256536
  }
256187
256537
  async stage(manifest, observer) {
256538
+ while (this.inFlight !== null) {
256539
+ const flight2 = this.inFlight;
256540
+ if (flight2.version === manifest.version) {
256541
+ try {
256542
+ return await flight2.promise;
256543
+ } finally {
256544
+ const verification = flight2.verification;
256545
+ if (flight2.downloaded) {
256546
+ replayObserver(() => observer?.downloaded());
256547
+ }
256548
+ if (verification !== void 0) {
256549
+ replayObserver(() => observer?.verification(verification));
256550
+ }
256551
+ }
256552
+ }
256553
+ try {
256554
+ await flight2.promise;
256555
+ } catch {
256556
+ continue;
256557
+ }
256558
+ }
256559
+ const progress = {
256560
+ downloaded: false,
256561
+ verification: void 0
256562
+ };
256563
+ const operation = this.performStage(manifest, {
256564
+ downloaded: () => {
256565
+ progress.downloaded = true;
256566
+ observer?.downloaded();
256567
+ },
256568
+ verification: (outcome) => {
256569
+ progress.verification = outcome;
256570
+ observer?.verification(outcome);
256571
+ }
256572
+ });
256573
+ const flight = {
256574
+ version: manifest.version,
256575
+ get downloaded() {
256576
+ return progress.downloaded;
256577
+ },
256578
+ get verification() {
256579
+ return progress.verification;
256580
+ },
256581
+ promise: operation.finally(() => {
256582
+ if (this.inFlight === flight) {
256583
+ this.inFlight = null;
256584
+ }
256585
+ })
256586
+ };
256587
+ this.inFlight = flight;
256588
+ return flight.promise;
256589
+ }
256590
+ async performStage(manifest, observer) {
256188
256591
  const platform2 = currentPlatformKey();
256189
256592
  const artifact = selectArtifact(manifest, platform2);
256190
256593
  if (!artifact) {
@@ -256226,11 +256629,13 @@ var init_UpdateStager = __esm({
256226
256629
  const sourceEntry = findPayloadEntry(extractedPath);
256227
256630
  const minClientProtocol = this.readMinClientProtocol(path55.dirname(sourceEntry));
256228
256631
  const installed3 = this.install(manifest.version, sourceEntry);
256632
+ this.stagedInProcess.add(installed3.version);
256229
256633
  const active = this.readActive();
256230
256634
  const running = this.runningVersion();
256231
256635
  pruneOldVersions(this.configHome, {
256232
256636
  ...active ? { active } : {},
256233
256637
  ...running ? { running } : {},
256638
+ protect: Array.from(this.stagedInProcess),
256234
256639
  extra: 1
256235
256640
  });
256236
256641
  return {
@@ -258264,7 +258669,7 @@ function probeSharedDaemonOnce(port, timeoutMs, expected) {
258264
258669
  settled = true;
258265
258670
  resolve15(outcome);
258266
258671
  };
258267
- const request3 = http.get(
258672
+ const request4 = http.get(
258268
258673
  {
258269
258674
  host: "127.0.0.1",
258270
258675
  port,
@@ -258298,18 +258703,18 @@ function probeSharedDaemonOnce(port, timeoutMs, expected) {
258298
258703
  response.on("close", () => settle2({ kind: "connection-lost" }));
258299
258704
  }
258300
258705
  );
258301
- request3.on("timeout", () => {
258302
- request3.destroy();
258706
+ request4.on("timeout", () => {
258707
+ request4.destroy();
258303
258708
  settle2({ kind: "timeout" });
258304
258709
  });
258305
- request3.on("error", (err) => {
258710
+ request4.on("error", (err) => {
258306
258711
  settle2({ kind: err.code === "ECONNREFUSED" ? "refused" : "connection-lost" });
258307
258712
  });
258308
258713
  });
258309
258714
  }
258310
258715
  function isTokenAccepted(port, token, timeoutMs) {
258311
258716
  return new Promise((resolve15) => {
258312
- const request3 = http.get(
258717
+ const request4 = http.get(
258313
258718
  {
258314
258719
  host: "127.0.0.1",
258315
258720
  port,
@@ -258322,11 +258727,11 @@ function isTokenAccepted(port, token, timeoutMs) {
258322
258727
  resolve15(response.statusCode !== 401 && response.statusCode !== 403);
258323
258728
  }
258324
258729
  );
258325
- request3.on("timeout", () => {
258326
- request3.destroy();
258730
+ request4.on("timeout", () => {
258731
+ request4.destroy();
258327
258732
  resolve15(true);
258328
258733
  });
258329
- request3.on("error", () => resolve15(true));
258734
+ request4.on("error", () => resolve15(true));
258330
258735
  });
258331
258736
  }
258332
258737
 
@@ -258535,7 +258940,7 @@ async function uninstallCommand(deps = {}) {
258535
258940
  }
258536
258941
  }
258537
258942
  const launcher = platformLauncherPath2(platform2, configHome);
258538
- const unit = unitFor(platform2, launcher, configHome, nodePath);
258943
+ const unit = unitFor(platform2, launcher, configHome, nodePath, process.env);
258539
258944
  const grainCommand = path30.join(configHome, "bin", platform2 === "win32" ? "grain.cmd" : "grain");
258540
258945
  const ownedPaths = [
258541
258946
  grainCommand,
@@ -258861,7 +259266,7 @@ async function openCommand(configDir = resolveGrainHome(), runner = createComman
258861
259266
  ]);
258862
259267
  if (result.exitCode !== 0) {
258863
259268
  console.error(
258864
- `Opening a browser failed. Run \`grain ui --url\` and paste the link it prints into any browser.`
259269
+ `Opening a browser failed for ${cleanUrl}. Run \`grain ui --url\` and paste the link it prints into any browser.`
258865
259270
  );
258866
259271
  return 1;
258867
259272
  }
@@ -258878,6 +259283,7 @@ init_supervisedStart();
258878
259283
 
258879
259284
  // src/server/cli/toolCommands.ts
258880
259285
  var fs30 = __toESM(require("fs"));
259286
+ init_callPolicy();
258881
259287
 
258882
259288
  // node_modules/@modelcontextprotocol/sdk/dist/esm/client/index.js
258883
259289
  init_protocol();
@@ -259035,8 +259441,8 @@ var ExperimentalClientTasks = class {
259035
259441
  *
259036
259442
  * @experimental
259037
259443
  */
259038
- requestStream(request3, resultSchema, options) {
259039
- return this._client.requestStream(request3, resultSchema, options);
259444
+ requestStream(request4, resultSchema, options) {
259445
+ return this._client.requestStream(request4, resultSchema, options);
259040
259446
  }
259041
259447
  };
259042
259448
 
@@ -259167,8 +259573,8 @@ var Client = class extends Protocol {
259167
259573
  }
259168
259574
  const method = methodValue;
259169
259575
  if (method === "elicitation/create") {
259170
- const wrappedHandler = async (request3, extra) => {
259171
- const validatedRequest = safeParse3(ElicitRequestSchema, request3);
259576
+ const wrappedHandler = async (request4, extra) => {
259577
+ const validatedRequest = safeParse3(ElicitRequestSchema, request4);
259172
259578
  if (!validatedRequest.success) {
259173
259579
  const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
259174
259580
  throw new McpError(ErrorCode.InvalidParams, `Invalid elicitation request: ${errorMessage}`);
@@ -259182,7 +259588,7 @@ var Client = class extends Protocol {
259182
259588
  if (params.mode === "url" && !supportsUrlMode) {
259183
259589
  throw new McpError(ErrorCode.InvalidParams, "Client does not support URL-mode elicitation requests");
259184
259590
  }
259185
- const result = await Promise.resolve(handler(request3, extra));
259591
+ const result = await Promise.resolve(handler(request4, extra));
259186
259592
  if (params.task) {
259187
259593
  const taskValidationResult = safeParse3(CreateTaskResultSchema, result);
259188
259594
  if (!taskValidationResult.success) {
@@ -259211,14 +259617,14 @@ var Client = class extends Protocol {
259211
259617
  return super.setRequestHandler(requestSchema, wrappedHandler);
259212
259618
  }
259213
259619
  if (method === "sampling/createMessage") {
259214
- const wrappedHandler = async (request3, extra) => {
259215
- const validatedRequest = safeParse3(CreateMessageRequestSchema, request3);
259620
+ const wrappedHandler = async (request4, extra) => {
259621
+ const validatedRequest = safeParse3(CreateMessageRequestSchema, request4);
259216
259622
  if (!validatedRequest.success) {
259217
259623
  const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
259218
259624
  throw new McpError(ErrorCode.InvalidParams, `Invalid sampling request: ${errorMessage}`);
259219
259625
  }
259220
259626
  const { params } = validatedRequest.data;
259221
- const result = await Promise.resolve(handler(request3, extra));
259627
+ const result = await Promise.resolve(handler(request4, extra));
259222
259628
  if (params.task) {
259223
259629
  const taskValidationResult = safeParse3(CreateTaskResultSchema, result);
259224
259630
  if (!taskValidationResult.success) {
@@ -259589,7 +259995,7 @@ async function callTool(name, args, deps = {}) {
259589
259995
  }
259590
259996
 
259591
259997
  // src/server/cli/toolCommands.ts
259592
- var TOOL_COMMANDS = [
259998
+ var ALL_TOOL_COMMANDS = [
259593
259999
  { words: ["connectors"], tool: "list_connectors", usage: "connectors" },
259594
260000
  { words: ["connections", "list"], tool: "list_connections", usage: "connections list" },
259595
260001
  {
@@ -259693,6 +260099,9 @@ var TOOL_COMMANDS = [
259693
260099
  { words: ["ledger", "stats"], tool: "ledger_stats", usage: "ledger stats" },
259694
260100
  { words: ["ledger", "verify"], tool: "verify_ledger", usage: "ledger verify" }
259695
260101
  ];
260102
+ var TOOL_COMMANDS = ALL_TOOL_COMMANDS.filter(
260103
+ (command) => alphaToolEnabled(command.tool)
260104
+ );
259696
260105
  var DATA_COMMAND_WORDS = new Set(TOOL_COMMANDS.map((command) => command.words[0]));
259697
260106
  function dataCommandHelp() {
259698
260107
  return TOOL_COMMANDS.map((command) => ` ${command.usage}`).join("\n");