devchain-cli 0.12.2 → 0.12.3

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.
Files changed (60) hide show
  1. package/README.md +4 -0
  2. package/dist/cli.js +154 -33
  3. package/dist/server/common/config/env.config.d.ts +1 -1
  4. package/dist/server/common/config/env.config.js +9 -1
  5. package/dist/server/common/config/env.config.js.map +1 -1
  6. package/dist/server/common/config/host-helpers.d.ts +7 -0
  7. package/dist/server/common/config/host-helpers.js +34 -0
  8. package/dist/server/common/config/host-helpers.js.map +1 -0
  9. package/dist/server/main.js +5 -3
  10. package/dist/server/main.js.map +1 -1
  11. package/dist/server/modules/core/core-normal.module.js +3 -2
  12. package/dist/server/modules/core/core-normal.module.js.map +1 -1
  13. package/dist/server/modules/core/services/gemini-trusted-folders.service.d.ts +26 -0
  14. package/dist/server/modules/core/services/gemini-trusted-folders.service.js +181 -0
  15. package/dist/server/modules/core/services/gemini-trusted-folders.service.js.map +1 -0
  16. package/dist/server/modules/core/services/preflight.service.js +2 -1
  17. package/dist/server/modules/core/services/preflight.service.js.map +1 -1
  18. package/dist/server/modules/core/services/provider-mcp-ensure.service.d.ts +10 -1
  19. package/dist/server/modules/core/services/provider-mcp-ensure.service.js +86 -19
  20. package/dist/server/modules/core/services/provider-mcp-ensure.service.js.map +1 -1
  21. package/dist/server/modules/mcp/services/mcp-provider-registration.service.d.ts +1 -0
  22. package/dist/server/modules/mcp/services/mcp-provider-registration.service.js +91 -4
  23. package/dist/server/modules/mcp/services/mcp-provider-registration.service.js.map +1 -1
  24. package/dist/server/modules/projects/controllers/projects.controller.d.ts +4 -1
  25. package/dist/server/modules/projects/controllers/projects.controller.js +1 -1
  26. package/dist/server/modules/projects/controllers/projects.controller.js.map +1 -1
  27. package/dist/server/modules/projects/projects.module.js +11 -2
  28. package/dist/server/modules/projects/projects.module.js.map +1 -1
  29. package/dist/server/modules/projects/services/project-provider-provisioning.service.d.ts +18 -0
  30. package/dist/server/modules/projects/services/project-provider-provisioning.service.js +92 -0
  31. package/dist/server/modules/projects/services/project-provider-provisioning.service.js.map +1 -0
  32. package/dist/server/modules/projects/services/projects.service.d.ts +9 -2
  33. package/dist/server/modules/projects/services/projects.service.js +31 -4
  34. package/dist/server/modules/projects/services/projects.service.js.map +1 -1
  35. package/dist/server/modules/providers/adapters/gemini.adapter.d.ts +2 -0
  36. package/dist/server/modules/providers/adapters/gemini.adapter.js +8 -3
  37. package/dist/server/modules/providers/adapters/gemini.adapter.js.map +1 -1
  38. package/dist/server/modules/providers/adapters/provider-adapter.interface.d.ts +2 -0
  39. package/dist/server/modules/providers/controllers/providers.controller.d.ts +1 -0
  40. package/dist/server/modules/providers/controllers/providers.controller.js +1 -0
  41. package/dist/server/modules/providers/controllers/providers.controller.js.map +1 -1
  42. package/dist/server/modules/sessions/services/sessions.service.js +10 -1
  43. package/dist/server/modules/sessions/services/sessions.service.js.map +1 -1
  44. package/dist/server/templates/3-agents-dev.json +111 -64
  45. package/dist/server/templates/5-agents-dev.json +152 -105
  46. package/dist/server/templates/teams-dev.json +155 -104
  47. package/dist/server/test-setup-node.js +7 -1
  48. package/dist/server/test-setup-node.js.map +1 -1
  49. package/dist/server/test-setup.js +7 -1
  50. package/dist/server/test-setup.js.map +1 -1
  51. package/dist/server/tsconfig.tsbuildinfo +1 -1
  52. package/dist/server/ui/assets/{ReviewDetailPage-D0vzq3rI.js → ReviewDetailPage-Dy3PfRrg.js} +1 -1
  53. package/dist/server/ui/assets/{ReviewsPage-aX6m8vW_.js → ReviewsPage-DUPZ_NtL.js} +1 -1
  54. package/dist/server/ui/assets/{index-Cut7Gl_8.js → index-CIlp3VXc.js} +167 -167
  55. package/dist/server/ui/assets/{useReviewSubscription-CrgRqMXe.js → useReviewSubscription-jEyfNAEJ.js} +1 -1
  56. package/dist/server/ui/index.html +1 -1
  57. package/dist/templates/3-agents-dev.json +111 -64
  58. package/dist/templates/5-agents-dev.json +152 -105
  59. package/dist/templates/teams-dev.json +155 -104
  60. package/package.json +14 -3
package/README.md CHANGED
@@ -89,6 +89,9 @@ devchain start --project /path/to/your/project
89
89
  # Run in foreground with logs
90
90
  devchain start --foreground
91
91
 
92
+ # Bind to all interfaces for VM/remote browser access (prints loud security warning)
93
+ devchain start --host 0.0.0.0
94
+
92
95
  # Stop the server
93
96
  devchain stop
94
97
  ```
@@ -108,6 +111,7 @@ On first run, import a template from the project page to provision your agent te
108
111
  | Option | Description |
109
112
  |--------|-------------|
110
113
  | `-p, --port <number>` | Port to run on (default: 3000 or next available) |
114
+ | `--host <address>` | Bind address (default: `127.0.0.1`; use `0.0.0.0` for remote/VM access — see [docs/setup.md](docs/setup.md)) |
111
115
  | `-f, --foreground` | Run in foreground with visible logs |
112
116
  | `--no-open` | Don't open browser automatically |
113
117
  | `--db <path>` | Custom database directory path |
package/dist/cli.js CHANGED
@@ -62,6 +62,87 @@ function isNewerVersion(latest, current) {
62
62
  return false;
63
63
  }
64
64
 
65
+ // ── Host normalization + URL builder helpers ──────────────────────────────────
66
+
67
+ function normalizeHost(input) {
68
+ const raw = input ?? '';
69
+
70
+ // Check for control characters before trimming (trim strips \n, \t, etc.)
71
+ for (let i = 0; i < raw.length; i++) {
72
+ const code = raw.charCodeAt(i);
73
+ if (code < 0x20 || code === 0x7f) {
74
+ throw new Error(`Invalid host: contains control characters`);
75
+ }
76
+ }
77
+
78
+ const trimmed = raw.trim();
79
+ if (!trimmed) return '127.0.0.1';
80
+
81
+ if (/^https?:\/\//i.test(trimmed)) {
82
+ throw new Error(`Invalid host "${trimmed}": pass a hostname or IP, not a URL`);
83
+ }
84
+
85
+ if (trimmed === '*') {
86
+ throw new Error(
87
+ 'Invalid host "*": use 0.0.0.0 for all IPv4 interfaces or :: for all IPv6 interfaces',
88
+ );
89
+ }
90
+
91
+ if (/^\[.*\]$/.test(trimmed)) {
92
+ const inner = trimmed.slice(1, -1);
93
+ throw new Error(`Invalid host "${trimmed}": drop the brackets — use ${inner}`);
94
+ }
95
+
96
+ // Distinguish IPv6 from host:port — IPv6 has 2+ colons or starts with : or contains ::
97
+ const colonCount = (trimmed.match(/:/g) || []).length;
98
+ const looksLikeIpv6 = colonCount >= 2 || trimmed.startsWith(':') || trimmed.includes('::');
99
+
100
+ if (!looksLikeIpv6 && colonCount === 1) {
101
+ throw new Error(
102
+ `Invalid host "${trimmed}": looks like host:port — pass only the host part`,
103
+ );
104
+ }
105
+
106
+ return trimmed;
107
+ }
108
+
109
+ function isWildcardHost(host) {
110
+ return host === '0.0.0.0' || host === '::';
111
+ }
112
+
113
+ function isNonLoopbackHost(host) {
114
+ if (isWildcardHost(host)) return true;
115
+ const lower = host.toLowerCase();
116
+ return lower !== '127.0.0.1' && lower !== '::1' && lower !== 'localhost';
117
+ }
118
+
119
+ function connectableHost(host) {
120
+ if (host === '0.0.0.0') return '127.0.0.1';
121
+ if (host === '::') return '::1';
122
+ return host;
123
+ }
124
+
125
+ function formatHostForUrl(host) {
126
+ if (/^\[.*\]$/.test(host)) {
127
+ throw new Error(`formatHostForUrl received already-bracketed input: ${host}`);
128
+ }
129
+ // IPv6 detection: contains colon(s)
130
+ if (host.includes(':')) return `[${host}]`;
131
+ return host;
132
+ }
133
+
134
+ function buildInternalBaseUrl({ host, port }) {
135
+ return `http://${formatHostForUrl(connectableHost(host))}:${port}`;
136
+ }
137
+
138
+ function buildDisplayUrls({ host, port }) {
139
+ return {
140
+ primary: buildInternalBaseUrl({ host, port }),
141
+ };
142
+ }
143
+
144
+ // ── End host helpers ──────────────────────────────────────────────────────────
145
+
65
146
  function getChangelogBetweenVersions(changelog, fromVersion, toVersion) {
66
147
  if (!changelog || typeof changelog !== 'object') return [];
67
148
 
@@ -486,7 +567,7 @@ function resolveDevchainApiBaseUrlForRestart({
486
567
  );
487
568
  }
488
569
 
489
- return `http://127.0.0.1:${port}`;
570
+ return buildInternalBaseUrl({ host: pidData.host || '127.0.0.1', port });
490
571
  }
491
572
 
492
573
  function normalizeWorktreeListPayload(payload) {
@@ -956,9 +1037,9 @@ function getPidFilePath() {
956
1037
  return join(devchainDir, 'devchain.pid');
957
1038
  }
958
1039
 
959
- function writePidFile(port) {
1040
+ function writePidFile(port, host) {
960
1041
  const pidFile = getPidFilePath();
961
- const data = JSON.stringify({ pid: process.pid, port, timestamp: Date.now() });
1042
+ const data = JSON.stringify({ pid: process.pid, port, host: host || '127.0.0.1', timestamp: Date.now() });
962
1043
  writeFileSync(pidFile, data, 'utf8');
963
1044
  }
964
1045
 
@@ -969,7 +1050,9 @@ function readPidFile() {
969
1050
  }
970
1051
  try {
971
1052
  const data = readFileSync(pidFile, 'utf8');
972
- return JSON.parse(data);
1053
+ const parsed = JSON.parse(data);
1054
+ if (parsed && !parsed.host) parsed.host = '127.0.0.1';
1055
+ return parsed;
973
1056
  } catch {
974
1057
  return null;
975
1058
  }
@@ -1287,6 +1370,7 @@ async function main(argv) {
1287
1370
  .command('start [args...]')
1288
1371
  .description('Start the Devchain local app')
1289
1372
  .option('-p, --port <number>', 'Port to listen on (default: 3000 or next free)')
1373
+ .option('--host <address>', 'Host/bind address (default: 127.0.0.1; use 0.0.0.0 for all IPv4 interfaces, :: for all IPv6)')
1290
1374
  .option('-f, --foreground', 'Run in foreground (attached to terminal). Shows startup output with colors and spinners.')
1291
1375
  .option('-d, --detach', 'Run in background as a detached process (default). Use "devchain stop" to stop it.')
1292
1376
  .option('--no-open', 'Do not open a browser window')
@@ -1337,7 +1421,7 @@ async function main(argv) {
1337
1421
  const existingPid = readPidFile();
1338
1422
  if (existingPid && isProcessRunning(existingPid.pid)) {
1339
1423
  console.error(`Devchain is already running (PID ${existingPid.pid}, port ${existingPid.port})`);
1340
- console.error(`Access it at: http://127.0.0.1:${existingPid.port}`);
1424
+ console.error(`Access it at: ${buildDisplayUrls({ host: existingPid.host || '127.0.0.1', port: existingPid.port }).primary}`);
1341
1425
  console.error('Use "devchain stop" to stop it first.');
1342
1426
  process.exit(1);
1343
1427
  }
@@ -1435,6 +1519,35 @@ async function main(argv) {
1435
1519
  port = await getPort({ port: preferPort });
1436
1520
  }
1437
1521
 
1522
+ // Resolve effective host before detach so child inherits normalized HOST env.
1523
+ // The --host flag also flows through childArgs (detach filter only strips --port
1524
+ // and --detach), so the child receives the effective host via two independent paths.
1525
+ let effectiveHost;
1526
+ try {
1527
+ effectiveHost = normalizeHost(opts.host ?? process.env.HOST ?? '');
1528
+ } catch (e) {
1529
+ console.error(e.message);
1530
+ process.exit(1);
1531
+ }
1532
+ process.env.HOST = effectiveHost;
1533
+
1534
+ // Security warning for non-loopback bind (before detach so parent terminal sees it)
1535
+ if (!worktreeRuntimeMode && isNonLoopbackHost(effectiveHost)) {
1536
+ console.error('');
1537
+ console.error(`⚠ DevChain is binding to ${effectiveHost}. There is no remote authentication`);
1538
+ console.error(' boundary; the API, terminals, MCP, and project files are exposed');
1539
+ console.error(' to anyone who can reach this address. Use only on a trusted');
1540
+ console.error(' network, VPN, or behind firewall rules.');
1541
+ if (opts.dev) {
1542
+ console.error('');
1543
+ console.error(' Note: --dev mode runs the UI on a separate Vite dev server bound to');
1544
+ console.error(' 127.0.0.1 only. Remote access affects the API server only. For full');
1545
+ console.error(' remote access including the UI dev server, use production mode');
1546
+ console.error(' (no --dev flag).');
1547
+ }
1548
+ console.error('');
1549
+ }
1550
+
1438
1551
  // === DETACH POINT ===
1439
1552
  // All interactive prompts are done. Now spawn the detached child if needed.
1440
1553
  if (shouldDetach) {
@@ -1473,9 +1586,8 @@ async function main(argv) {
1473
1586
  process.exit(0);
1474
1587
  }
1475
1588
 
1476
- // Apply env before requiring the server
1589
+ // Apply env before requiring the server (HOST already set pre-detach)
1477
1590
  process.env.PORT = String(port);
1478
- process.env.HOST = process.env.HOST || '127.0.0.1';
1479
1591
  process.env.NODE_ENV = process.env.NODE_ENV || 'production';
1480
1592
  const dbEnv = parseDbPath(opts.db);
1481
1593
  if (dbEnv.DB_PATH) process.env.DB_PATH = dbEnv.DB_PATH;
@@ -1534,10 +1646,11 @@ async function main(argv) {
1534
1646
  detached: platform() !== 'win32', // Create process group on Unix
1535
1647
  });
1536
1648
 
1537
- const baseUrl = `http://${process.env.HOST}:${port}`;
1649
+ const internalBaseUrl = buildInternalBaseUrl({ host: effectiveHost, port });
1650
+ const displayUrl = buildDisplayUrls({ host: effectiveHost, port }).primary;
1538
1651
 
1539
1652
  // Wait for API to be ready (longer timeout for dev mode compilation)
1540
- const ready = await waitForHealth(`${baseUrl}/health`, { timeoutMs: 60000 });
1653
+ const ready = await waitForHealth(`${internalBaseUrl}/health`, { timeoutMs: 60000 });
1541
1654
  if (!ready) {
1542
1655
  cli.error('API did not become ready in time');
1543
1656
  killProcessGroup(nestProcess);
@@ -1545,8 +1658,8 @@ async function main(argv) {
1545
1658
  }
1546
1659
 
1547
1660
  cli.blank();
1548
- cli.success(`API ready at ${baseUrl}`);
1549
- cli.info(`API docs: ${baseUrl}/api/docs`);
1661
+ cli.success(`API ready at ${displayUrl}`);
1662
+ cli.info(`API docs: ${displayUrl}/api/docs`);
1550
1663
 
1551
1664
  // Ensure provider rows exist
1552
1665
  if (
@@ -1554,7 +1667,7 @@ async function main(argv) {
1554
1667
  && opts.__providersDetected
1555
1668
  && opts.__providersDetected.size > 0
1556
1669
  ) {
1557
- await ensureProvidersInDb(baseUrl, opts.__providersDetected, log);
1670
+ await ensureProvidersInDb(internalBaseUrl, opts.__providersDetected, log);
1558
1671
  }
1559
1672
 
1560
1673
  // Determine startup path for MCP validation
@@ -1564,7 +1677,7 @@ async function main(argv) {
1564
1677
 
1565
1678
  // Validate MCP for all providers
1566
1679
  if (!worktreeRuntimeMode) {
1567
- await validateMcpForProviders(baseUrl, cli, opts, log, startupPath);
1680
+ await validateMcpForProviders(internalBaseUrl, cli, opts, log, startupPath);
1568
1681
  }
1569
1682
 
1570
1683
  // Note: Claude bypass prompt already handled before server start
@@ -1585,12 +1698,12 @@ async function main(argv) {
1585
1698
  cli.blank();
1586
1699
  cli.success('Development servers running');
1587
1700
  cli.info(`${devUiConfig.logLabel}: ${devUiConfig.url}`);
1588
- cli.info(`API: ${baseUrl}`);
1701
+ cli.info(`API: ${displayUrl}`);
1589
1702
  cli.blank();
1590
1703
 
1591
1704
  // Write PID file for top-level runtime only
1592
1705
  if (!worktreeRuntimeMode) {
1593
- writePidFile(port);
1706
+ writePidFile(port, effectiveHost);
1594
1707
  }
1595
1708
 
1596
1709
  // Handle cleanup on exit - kill entire process groups
@@ -1640,10 +1753,11 @@ async function main(argv) {
1640
1753
  // eslint-disable-next-line @typescript-eslint/no-var-requires
1641
1754
  require(serverEntry);
1642
1755
 
1643
- const baseUrl = `http://${process.env.HOST}:${port}`;
1644
- const ready = await waitForHealth(`${baseUrl}/health`);
1756
+ const internalBaseUrl = buildInternalBaseUrl({ host: effectiveHost, port });
1757
+ const displayUrl = buildDisplayUrls({ host: effectiveHost, port }).primary;
1758
+ const ready = await waitForHealth(`${internalBaseUrl}/health`);
1645
1759
  if (!ready) {
1646
- log('error', 'Server did not become ready in time', { url: baseUrl });
1760
+ log('error', 'Server did not become ready in time', { url: internalBaseUrl });
1647
1761
  if (spinner) {
1648
1762
  spinner.stop('✗ timeout');
1649
1763
  cli.blank();
@@ -1656,15 +1770,15 @@ async function main(argv) {
1656
1770
  }
1657
1771
 
1658
1772
  if (opts.foreground) {
1659
- log('info', `Devchain is running at ${baseUrl}`);
1660
- log('info', `API docs: ${baseUrl}/api/docs`);
1661
- console.log(`\nDevchain is running at ${baseUrl}`);
1662
- console.log(`API docs: ${baseUrl}/api/docs`);
1773
+ log('info', `Devchain is running at ${displayUrl}`);
1774
+ log('info', `API docs: ${displayUrl}/api/docs`);
1775
+ console.log(`\nDevchain is running at ${displayUrl}`);
1776
+ console.log(`API docs: ${displayUrl}/api/docs`);
1663
1777
  console.log('Press Ctrl+C to stop.\n');
1664
1778
  } else {
1665
1779
  cli.blank();
1666
- cli.success(`Server ready at ${baseUrl}`);
1667
- cli.info(`API docs: ${baseUrl}/api/docs`);
1780
+ cli.success(`Server ready at ${displayUrl}`);
1781
+ cli.info(`API docs: ${displayUrl}/api/docs`);
1668
1782
  }
1669
1783
 
1670
1784
  // Ensure provider rows exist (idempotent) before opening UI
@@ -1673,7 +1787,7 @@ async function main(argv) {
1673
1787
  && opts.__providersDetected
1674
1788
  && opts.__providersDetected.size > 0
1675
1789
  ) {
1676
- await ensureProvidersInDb(baseUrl, opts.__providersDetected, log);
1790
+ await ensureProvidersInDb(internalBaseUrl, opts.__providersDetected, log);
1677
1791
  }
1678
1792
 
1679
1793
  // Determine startup path for MCP validation and URL
@@ -1683,19 +1797,19 @@ async function main(argv) {
1683
1797
 
1684
1798
  // Validate MCP for all providers (with project context)
1685
1799
  if (!worktreeRuntimeMode) {
1686
- await validateMcpForProviders(baseUrl, cli, opts, log, startupPath);
1800
+ await validateMcpForProviders(internalBaseUrl, cli, opts, log, startupPath);
1687
1801
  }
1688
1802
 
1689
1803
  // Note: Claude bypass prompt already handled before server start (in parent process for detach mode)
1690
1804
 
1691
1805
  // Determine URL to open based on project path
1692
- let urlToOpen = baseUrl;
1806
+ let urlToOpen = displayUrl;
1693
1807
  try {
1694
- const byPathUrl = `${baseUrl}/api/projects/by-path?path=${encodeURIComponent(startupPath)}`;
1808
+ const byPathUrl = `${internalBaseUrl}/api/projects/by-path?path=${encodeURIComponent(startupPath)}`;
1695
1809
  const resByPath = await fetchWithTimeout(byPathUrl, {}, 2500);
1696
1810
  if (resByPath.ok) {
1697
1811
  const project = await resByPath.json();
1698
- urlToOpen = `${baseUrl}/projects?projectId=${encodeURIComponent(project.id)}`;
1812
+ urlToOpen = `${displayUrl}/projects?projectId=${encodeURIComponent(project.id)}`;
1699
1813
  if (opts.foreground) {
1700
1814
  log('info', 'Resolved startup path to existing project', { startupPath, projectId: project.id });
1701
1815
  } else if (opts.open) {
@@ -1703,7 +1817,7 @@ async function main(argv) {
1703
1817
  }
1704
1818
  } else {
1705
1819
  // 404 or invalid — fall back to newProjectPath to prefill dialog
1706
- urlToOpen = `${baseUrl}/projects?newProjectPath=${encodeURIComponent(startupPath)}`;
1820
+ urlToOpen = `${displayUrl}/projects?newProjectPath=${encodeURIComponent(startupPath)}`;
1707
1821
  if (opts.foreground) {
1708
1822
  log('info', 'No project at startup path; prefill create dialog', { startupPath });
1709
1823
  } else if (opts.open) {
@@ -1712,7 +1826,7 @@ async function main(argv) {
1712
1826
  }
1713
1827
  } catch (e) {
1714
1828
  // Network/timeouts: still prefer prefilled create dialog
1715
- urlToOpen = `${baseUrl}/projects?newProjectPath=${encodeURIComponent(startupPath)}`;
1829
+ urlToOpen = `${displayUrl}/projects?newProjectPath=${encodeURIComponent(startupPath)}`;
1716
1830
  if (opts.foreground) {
1717
1831
  log('warn', 'Failed to resolve startup path; opening create dialog', {
1718
1832
  error: e instanceof Error ? e.message : String(e),
@@ -1736,7 +1850,7 @@ async function main(argv) {
1736
1850
 
1737
1851
  if (!worktreeRuntimeMode) {
1738
1852
  // Write PID file for stop command
1739
- writePidFile(port);
1853
+ writePidFile(port, effectiveHost);
1740
1854
 
1741
1855
  // Clean up PID file on exit (main.ts handles SIGINT/SIGTERM and graceful shutdown)
1742
1856
  process.on('exit', () => {
@@ -1820,7 +1934,7 @@ async function main(argv) {
1820
1934
  console.log('No running Devchain instance found.');
1821
1935
  process.exit(1);
1822
1936
  } else {
1823
- const { pid, port } = pidData;
1937
+ const { pid, port, host } = pidData;
1824
1938
 
1825
1939
  if (!isProcessRunning(pid)) {
1826
1940
  console.log(`Devchain process (PID ${pid}) is not running. Cleaning up stale PID file.`);
@@ -1877,6 +1991,13 @@ module.exports = {
1877
1991
  main,
1878
1992
  normalizeCliArgv,
1879
1993
  __test__: {
1994
+ normalizeHost,
1995
+ isWildcardHost,
1996
+ isNonLoopbackHost,
1997
+ connectableHost,
1998
+ formatHostForUrl,
1999
+ buildInternalBaseUrl,
2000
+ buildDisplayUrls,
1880
2001
  ensureDockerAvailable,
1881
2002
  isDockerAvailable,
1882
2003
  deriveRepoRootFromGit,
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  declare const envSchema: z.ZodEffects<z.ZodEffects<z.ZodObject<{
3
3
  NODE_ENV: z.ZodDefault<z.ZodEnum<["development", "production", "test"]>>;
4
4
  PORT: z.ZodDefault<z.ZodEffects<z.ZodString, number, string>>;
5
- HOST: z.ZodDefault<z.ZodString>;
5
+ HOST: z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodEffects<z.ZodDefault<z.ZodString>, string, string | undefined>, string, string | undefined>, string, string | undefined>, string, string | undefined>;
6
6
  LOG_LEVEL: z.ZodDefault<z.ZodEnum<["silent", "fatal", "error", "warn", "info", "debug", "trace"]>>;
7
7
  DEVCHAIN_MODE: z.ZodDefault<z.ZodEnum<["normal", "main"]>>;
8
8
  DATABASE_URL: z.ZodOptional<z.ZodString>;
@@ -44,7 +44,15 @@ const envSchema = zod_1.z
44
44
  .object({
45
45
  NODE_ENV: zod_1.z.enum(['development', 'production', 'test']).default('development'),
46
46
  PORT: zod_1.z.string().regex(/^\d+$/).transform(Number).default('3000'),
47
- HOST: zod_1.z.string().default('127.0.0.1'),
47
+ HOST: zod_1.z
48
+ .string()
49
+ .default('127.0.0.1')
50
+ .transform((v) => v.trim())
51
+ .refine((v) => v.length > 0, { message: 'HOST must not be empty' })
52
+ .refine((v) => v !== '*', { message: 'HOST must not be "*"' })
53
+ .refine((v) => !/[\x00-\x1f\x7f]/.test(v), {
54
+ message: 'HOST must not contain control characters',
55
+ }),
48
56
  LOG_LEVEL: zod_1.z
49
57
  .enum(['silent', 'fatal', 'error', 'warn', 'info', 'debug', 'trace'])
50
58
  .default('info'),
@@ -1 +1 @@
1
- {"version":3,"file":"env.config.js","sourceRoot":"","sources":["../../../src/common/config/env.config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"env.config.js","sourceRoot":"","sources":["../../../src/common/config/env.config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function isWildcardHost(host: string): boolean;
2
+ export declare function connectableHost(host: string): string;
3
+ export declare function formatHostForUrl(host: string): string;
4
+ export declare function getRuntimeInternalBaseUrl(config: {
5
+ HOST: string;
6
+ PORT: number;
7
+ }): string;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isWildcardHost = isWildcardHost;
4
+ exports.connectableHost = connectableHost;
5
+ exports.formatHostForUrl = formatHostForUrl;
6
+ exports.getRuntimeInternalBaseUrl = getRuntimeInternalBaseUrl;
7
+ const IPV4_WILDCARDS = new Set(['0.0.0.0', '']);
8
+ const IPV6_WILDCARDS = new Set(['::', '[::]']);
9
+ function isWildcardHost(host) {
10
+ const trimmed = host.trim().toLowerCase();
11
+ return IPV4_WILDCARDS.has(trimmed) || IPV6_WILDCARDS.has(trimmed);
12
+ }
13
+ function connectableHost(host) {
14
+ const trimmed = host.trim();
15
+ if (isWildcardHost(trimmed)) {
16
+ if (IPV6_WILDCARDS.has(trimmed.toLowerCase())) {
17
+ return '::1';
18
+ }
19
+ return '127.0.0.1';
20
+ }
21
+ const unwrapped = trimmed.startsWith('[') && trimmed.endsWith(']') ? trimmed.slice(1, -1) : trimmed;
22
+ return unwrapped;
23
+ }
24
+ function formatHostForUrl(host) {
25
+ if (host.includes(':') && !host.startsWith('[')) {
26
+ return `[${host}]`;
27
+ }
28
+ return host;
29
+ }
30
+ function getRuntimeInternalBaseUrl(config) {
31
+ const host = connectableHost(config.HOST);
32
+ return `http://${formatHostForUrl(host)}:${config.PORT}`;
33
+ }
34
+ //# sourceMappingURL=host-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-helpers.js","sourceRoot":"","sources":["../../../src/common/config/host-helpers.ts"],"names":[],"mappings":";;AAGA,wCAGC;AAED,0CAWC;AAED,4CAKC;AAED,8DAGC;AA/BD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;AAChD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;AAE/C,SAAgB,cAAc,CAAC,IAAY;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,OAAO,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACpE,CAAC;AAED,SAAgB,eAAe,CAAC,IAAY;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,IAAI,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,MAAM,SAAS,GACb,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACpF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,IAAI,GAAG,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,yBAAyB,CAAC,MAAsC;IAC9E,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,UAAU,gBAAgB,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;AAC3D,CAAC"}
@@ -38,6 +38,7 @@ const platform_fastify_1 = require("@nestjs/platform-fastify");
38
38
  const swagger_1 = require("@nestjs/swagger");
39
39
  const common_1 = require("@nestjs/common");
40
40
  const env_config_1 = require("./common/config/env.config");
41
+ const host_helpers_1 = require("./common/config/host-helpers");
41
42
  const logger_1 = require("./common/logging/logger");
42
43
  const path_1 = require("path");
43
44
  const fs_1 = require("fs");
@@ -144,13 +145,14 @@ async function bootstrap() {
144
145
  appLogger.error({ error, portFile: config.RUNTIME_PORT_FILE }, 'Failed to write runtime port file');
145
146
  }
146
147
  }
148
+ const displayUrl = (0, host_helpers_1.getRuntimeInternalBaseUrl)({ HOST: config.HOST, PORT: actualPort });
147
149
  appLogger.info({
148
150
  mode,
149
151
  port: actualPort,
150
- host: config.HOST,
152
+ bindHost: config.HOST,
151
153
  env: config.NODE_ENV,
152
- }, `Application is running on: http://${config.HOST}:${actualPort}`);
153
- appLogger.info(`API Documentation: http://${config.HOST}:${actualPort}/api/docs`);
154
+ }, `Application is running on: ${displayUrl}`);
155
+ appLogger.info(`API Documentation: ${displayUrl}/api/docs`);
154
156
  }
155
157
  bootstrap().catch((error) => {
156
158
  logger_1.logger.fatal(error, 'Failed to start application');
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAA2C;AAC3C,+DAAkF;AAClF,6CAAiE;AACjE,2CAAgD;AAChD,2DAA0D;AAC1D,+DAAyE;AACzE,oDAA+D;AAC/D,+BAA4B;AAC5B,2BAAgC;AAEhC,KAAK,UAAU,SAAS;IACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;IACtE,MAAM,UAAU,GACd,IAAI,KAAK,MAAM;QACb,CAAC,CAAC,CAAC,wDAAa,mBAAmB,GAAC,CAAC,CAAC,aAAa;QACnD,CAAC,CAAC,CAAC,wDAAa,qBAAqB,GAAC,CAAC,CAAC,eAAe,CAAC;IAE5D,MAAM,MAAM,GAAG,IAAA,yBAAY,GAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAA,qBAAY,EAAC,WAAW,CAAC,CAAC;IAI5C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,MAAM,CAAC;IAChE,MAAM,SAAS,GAAkE,CAAC,GAAG,EAAE;QACrF,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,QAAQ,CAAC;YACd,KAAK,OAAO;gBACV,OAAO,KAAK,CAAC;YACf,KAAK,OAAO;gBACV,OAAO,CAAC,OAAO,CAAC,CAAC;YACnB,KAAK,MAAM;gBACT,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC3B,KAAK,MAAM,CAAC;YACZ,KAAK,KAAK;gBACR,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAClC,KAAK,OAAO;gBACV,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAC3C,KAAK,OAAO,CAAC;YACb,KAAK,SAAS;gBACZ,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YACtD;gBACE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAIL,MAAM,aAAa,GACjB,QAAQ,KAAK,OAAO;QAClB,CAAC,CAAC,KAAK;QACP,CAAC,CAAC;YACE,KAAK,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;SAC9E,CAAC;IAER,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAClC,UAAU,EACV,IAAI,iCAAc,CAAC;QACjB,MAAM,EAAE,aAAa;QACrB,iBAAiB,EAAE,WAAW;QAC9B,qBAAqB,EAAE,QAAQ,KAAK,OAAO;KAC5C,CAAC,EACF;QACE,MAAM,EAAE,SAAS;KAClB,CACF,CAAC;IAGF,MAAM,MAAM,GAAG,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,KAAK,YAAY,CAAC;IAEtD,IAAI,YAAY,IAAI,IAAA,eAAU,EAAC,MAAM,CAAC,EAAE,CAAC;QAEvC,MAAM,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE;YAC7C,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,GAAG;YACX,aAAa,EAAE,KAAK;YACpB,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;QACH,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,6BAA6B,CAAC,CAAC;IACxE,CAAC;SAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QACzB,SAAS,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;IAC5F,CAAC;SAAM,CAAC;QACN,SAAS,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;IAChF,CAAC;IAGD,GAAG,CAAC,cAAc,CAChB,IAAI,uBAAc,CAAC;QACjB,SAAS,EAAE,IAAI;QACf,oBAAoB,EAAE,IAAI;QAC1B,SAAS,EAAE,IAAI;KAChB,CAAC,CACH,CAAC;IAGF,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,MAAM,gBAAgB,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QAChD,IAAI,cAAc;YAAE,OAAO;QAC3B,cAAc,GAAG,IAAI,CAAC;QACtB,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,yDAAyD,CAAC,CAAC;QACtF,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;YAClB,SAAS,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,gCAAgC,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;IAGzD,MAAM,aAAa,GAAG,IAAI,yBAAe,EAAE;SACxC,QAAQ,CAAC,wBAAwB,CAAC;SAClC,cAAc,CAAC,wCAAwC,CAAC;SACxD,UAAU,CAAC,OAAO,CAAC;SACnB,MAAM,CAAC,QAAQ,EAAE,wBAAwB,CAAC;SAC1C,KAAK,EAAE,CAAC;IAEX,MAAM,QAAQ,GAAG,uBAAa,CAAC,cAAc,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAClE,uBAAa,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IAG/C,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAG3C,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,CAAC;IACpD,MAAM,UAAU,GACd,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IAGxF,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC7B,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,wDAAa,IAAI,GAAC,CAAC;QACxD,MAAM,EAAE,OAAO,EAAE,GAAG,wDAAa,MAAM,GAAC,CAAC;QACzC,IAAI,CAAC;YACH,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAClE,aAAa,CACX,MAAM,CAAC,iBAAiB,EACxB,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC,CACjF,CAAC;YACF,SAAS,CAAC,IAAI,CACZ,EAAE,QAAQ,EAAE,MAAM,CAAC,iBAAiB,EAAE,UAAU,EAAE,EAClD,2BAA2B,CAC5B,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,CAAC,KAAK,CACb,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,iBAAiB,EAAE,EAC7C,mCAAmC,CACpC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAA,wCAAyB,EAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IACtF,SAAS,CAAC,IAAI,CACZ;QACE,IAAI;QACJ,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,MAAM,CAAC,IAAI;QACrB,GAAG,EAAE,MAAM,CAAC,QAAQ;KACrB,EACD,8BAA8B,UAAU,EAAE,CAC3C,CAAC;IACF,SAAS,CAAC,IAAI,CAAC,sBAAsB,UAAU,WAAW,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC1B,eAAM,CAAC,KAAK,CAAC,KAAK,EAAE,6BAA6B,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -11,6 +11,7 @@ const common_1 = require("@nestjs/common");
11
11
  const preflight_controller_1 = require("./controllers/preflight.controller");
12
12
  const preflight_service_1 = require("./services/preflight.service");
13
13
  const provider_mcp_ensure_service_1 = require("./services/provider-mcp-ensure.service");
14
+ const gemini_trusted_folders_service_1 = require("./services/gemini-trusted-folders.service");
14
15
  const storage_module_1 = require("../storage/storage.module");
15
16
  const mcp_module_1 = require("../mcp/mcp.module");
16
17
  const adapters_1 = require("../providers/adapters");
@@ -21,8 +22,8 @@ exports.CoreNormalModule = CoreNormalModule = __decorate([
21
22
  (0, common_1.Module)({
22
23
  imports: [storage_module_1.StorageModule, (0, common_1.forwardRef)(() => mcp_module_1.McpModule), adapters_1.ProviderAdaptersModule],
23
24
  controllers: [preflight_controller_1.PreflightController],
24
- providers: [preflight_service_1.PreflightService, provider_mcp_ensure_service_1.ProviderMcpEnsureService],
25
- exports: [preflight_service_1.PreflightService, provider_mcp_ensure_service_1.ProviderMcpEnsureService],
25
+ providers: [preflight_service_1.PreflightService, provider_mcp_ensure_service_1.ProviderMcpEnsureService, gemini_trusted_folders_service_1.GeminiTrustedFoldersService],
26
+ exports: [preflight_service_1.PreflightService, provider_mcp_ensure_service_1.ProviderMcpEnsureService, gemini_trusted_folders_service_1.GeminiTrustedFoldersService],
26
27
  })
27
28
  ], CoreNormalModule);
28
29
  //# sourceMappingURL=core-normal.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"core-normal.module.js","sourceRoot":"","sources":["../../../src/modules/core/core-normal.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoD;AACpD,6EAAyE;AACzE,oEAAgE;AAChE,wFAAkF;AAClF,8DAA0D;AAC1D,kDAA8C;AAC9C,oDAA+D;AAQxD,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CAAG,CAAA;AAAnB,4CAAgB;2BAAhB,gBAAgB;IAN5B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,8BAAa,EAAE,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,sBAAS,CAAC,EAAE,iCAAsB,CAAC;QAC7E,WAAW,EAAE,CAAC,0CAAmB,CAAC;QAClC,SAAS,EAAE,CAAC,oCAAgB,EAAE,sDAAwB,CAAC;QACvD,OAAO,EAAE,CAAC,oCAAgB,EAAE,sDAAwB,CAAC;KACtD,CAAC;GACW,gBAAgB,CAAG"}
1
+ {"version":3,"file":"core-normal.module.js","sourceRoot":"","sources":["../../../src/modules/core/core-normal.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAoD;AACpD,6EAAyE;AACzE,oEAAgE;AAChE,wFAAkF;AAClF,8FAAwF;AACxF,8DAA0D;AAC1D,kDAA8C;AAC9C,oDAA+D;AAQxD,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CAAG,CAAA;AAAnB,4CAAgB;2BAAhB,gBAAgB;IAN5B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,8BAAa,EAAE,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,sBAAS,CAAC,EAAE,iCAAsB,CAAC;QAC7E,WAAW,EAAE,CAAC,0CAAmB,CAAC;QAClC,SAAS,EAAE,CAAC,oCAAgB,EAAE,sDAAwB,EAAE,4DAA2B,CAAC;QACpF,OAAO,EAAE,CAAC,oCAAgB,EAAE,sDAAwB,EAAE,4DAA2B,CAAC;KACnF,CAAC;GACW,gBAAgB,CAAG"}
@@ -0,0 +1,26 @@
1
+ type TrustLevel = 'TRUST_FOLDER' | 'TRUST_PARENT' | 'DO_NOT_TRUST';
2
+ export type EffectiveTrust = {
3
+ kind: 'trusted';
4
+ via: 'exact' | 'ancestor' | 'parent_rule';
5
+ } | {
6
+ kind: 'distrusted';
7
+ via: 'exact' | 'ancestor';
8
+ } | {
9
+ kind: 'no_rule';
10
+ };
11
+ export type EnsureTrustResult = {
12
+ success: boolean;
13
+ action: 'added' | 'already_trusted' | 'distrusted_warning' | 'malformed_warning';
14
+ message: string;
15
+ warnings?: string[];
16
+ };
17
+ export declare function getEffectiveTrust(projectPath: string, rules: Record<string, TrustLevel>): EffectiveTrust;
18
+ export declare class GeminiTrustedFoldersService {
19
+ private writeTail;
20
+ private get filePath();
21
+ ensure(projectPath: string): Promise<EnsureTrustResult>;
22
+ private doEnsure;
23
+ private atomicWrite;
24
+ private normalizePath;
25
+ }
26
+ export {};