@agent-native/core 0.78.3 → 0.78.4

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.
@@ -1,8 +1,7 @@
1
1
  import fs from "fs";
2
- import { createRequire } from "module";
2
+ import { createRequire, syncBuiltinESMExports } from "module";
3
3
  import path from "path";
4
4
  import { fileURLToPath } from "url";
5
- import { nitro as nitroVitePlugin } from "nitro/vite";
6
5
  import { getViteDevRecoveryScript } from "../client/vite-dev-recovery-script.js";
7
6
  import { findWorkspaceRoot } from "../scripts/utils.js";
8
7
  import { verifyEmbedSessionToken } from "../server/embed-session.js";
@@ -13,6 +12,48 @@ import { actionTypesPlugin } from "./action-types-plugin.js";
13
12
  import { agentsBundlePlugin } from "./agents-bundle-plugin.js";
14
13
  const require = createRequire(import.meta.url);
15
14
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
+ let nitroFsWatchGuardInstalled = false;
16
+ function installNitroFsWatchGuard() {
17
+ if (nitroFsWatchGuardInstalled)
18
+ return;
19
+ nitroFsWatchGuardInstalled = true;
20
+ const originalWatch = fs.watch.bind(fs);
21
+ fs.watch = (...args) => {
22
+ let watcher;
23
+ try {
24
+ watcher = originalWatch(...args);
25
+ }
26
+ catch (error) {
27
+ const err = error;
28
+ if (err.code !== "EMFILE" && err.code !== "ENOSPC")
29
+ throw error;
30
+ console.warn(`[agent-native] Disabled Nitro fs.watch for ${String(args[0])}: ${err.message}`);
31
+ return {
32
+ close() { },
33
+ on() {
34
+ return this;
35
+ },
36
+ };
37
+ }
38
+ const originalEmit = watcher.emit.bind(watcher);
39
+ watcher.emit = ((eventName, ...eventArgs) => {
40
+ const err = eventArgs[0];
41
+ if (eventName === "error" &&
42
+ (err?.code === "EMFILE" || err?.code === "ENOSPC")) {
43
+ console.warn(`[agent-native] Disabled Nitro fs.watch for ${String(args[0])}: ${err.message}`);
44
+ watcher.close();
45
+ return false;
46
+ }
47
+ return originalEmit(eventName, ...eventArgs);
48
+ });
49
+ return watcher;
50
+ };
51
+ syncBuiltinESMExports();
52
+ }
53
+ function nitroVitePlugin(...args) {
54
+ installNitroFsWatchGuard();
55
+ return require("nitro/vite").nitro(...args);
56
+ }
16
57
  /**
17
58
  * Sync discovery for the workspace-core in an enterprise monorepo.
18
59
  *
@@ -92,6 +133,79 @@ function findWorkspaceCoreSync(startDir) {
92
133
  }
93
134
  return null;
94
135
  }
136
+ function findLocalWorkspacePackageDeps(startDir, workspaceRoot) {
137
+ if (!workspaceRoot)
138
+ return [];
139
+ const pkgPath = path.join(startDir, "package.json");
140
+ if (!fs.existsSync(pkgPath))
141
+ return [];
142
+ try {
143
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
144
+ const deps = {
145
+ ...(pkg.dependencies ?? {}),
146
+ ...(pkg.devDependencies ?? {}),
147
+ ...(pkg.peerDependencies ?? {}),
148
+ };
149
+ const req = createRequire(pkgPath);
150
+ const seen = new Set();
151
+ const packages = [];
152
+ for (const [packageName, range] of Object.entries(deps)) {
153
+ if (!range.startsWith("workspace:"))
154
+ continue;
155
+ if (seen.has(packageName))
156
+ continue;
157
+ seen.add(packageName);
158
+ try {
159
+ const packageJsonPath = findInstalledPackageJsonPath(pkgPath, packageName) ??
160
+ findPackageJsonFromEntry(req.resolve(packageName));
161
+ if (!packageJsonPath)
162
+ continue;
163
+ const packageDir = fs.realpathSync(path.dirname(packageJsonPath));
164
+ if (!packageDir.startsWith(path.join(workspaceRoot, "packages")))
165
+ continue;
166
+ packages.push({ packageName, packageDir });
167
+ }
168
+ catch {
169
+ // Dependency may not have been installed yet; ignore it for dev config.
170
+ }
171
+ }
172
+ return packages;
173
+ }
174
+ catch {
175
+ return [];
176
+ }
177
+ }
178
+ function findInstalledPackageJsonPath(pkgPath, packageName) {
179
+ const candidate = path.join(path.dirname(pkgPath), "node_modules", ...packageName.split("/"), "package.json");
180
+ return fs.existsSync(candidate) ? candidate : null;
181
+ }
182
+ function findPackageJsonFromEntry(entryPath) {
183
+ let dir = fs.statSync(entryPath).isDirectory()
184
+ ? entryPath
185
+ : path.dirname(entryPath);
186
+ for (let i = 0; i < 20; i++) {
187
+ const candidate = path.join(dir, "package.json");
188
+ if (fs.existsSync(candidate))
189
+ return candidate;
190
+ const parent = path.dirname(dir);
191
+ if (parent === dir)
192
+ break;
193
+ dir = parent;
194
+ }
195
+ return null;
196
+ }
197
+ function findPnpmWorkspaceRoot(startDir) {
198
+ let dir = path.resolve(startDir);
199
+ for (let i = 0; i < 20; i++) {
200
+ if (fs.existsSync(path.join(dir, "pnpm-workspace.yaml")))
201
+ return dir;
202
+ const parent = path.dirname(dir);
203
+ if (parent === dir)
204
+ break;
205
+ dir = parent;
206
+ }
207
+ return null;
208
+ }
95
209
  /** Escape a string so it can be embedded as a regex literal. */
96
210
  function escapeRegex(s) {
97
211
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -1389,6 +1503,43 @@ function arrayFrom(value) {
1389
1503
  return [];
1390
1504
  return Array.isArray(value) ? value : [value];
1391
1505
  }
1506
+ function localWorkspacePackageAliases(packages) {
1507
+ const aliases = [];
1508
+ for (const { packageName, packageDir } of packages) {
1509
+ const pkgPath = path.join(packageDir, "package.json");
1510
+ if (!fs.existsSync(pkgPath))
1511
+ continue;
1512
+ try {
1513
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
1514
+ const exportsMap = pkg.exports;
1515
+ if (!exportsMap || typeof exportsMap !== "object")
1516
+ continue;
1517
+ for (const [exportPath, target] of Object.entries(exportsMap)) {
1518
+ if (typeof target !== "string")
1519
+ continue;
1520
+ const importPath = exportPath === "."
1521
+ ? packageName
1522
+ : `${packageName}${exportPath.slice(1)}`;
1523
+ const replacement = path.resolve(packageDir, target);
1524
+ if (importPath.includes("*") || replacement.includes("*")) {
1525
+ aliases.push({
1526
+ find: new RegExp(`^${escapeRegex(importPath).replace("\\*", "(.+)")}$`),
1527
+ replacement: replacement.replace("*", "$1"),
1528
+ });
1529
+ continue;
1530
+ }
1531
+ aliases.push({
1532
+ find: new RegExp(`^${escapeRegex(importPath)}$`),
1533
+ replacement,
1534
+ });
1535
+ }
1536
+ }
1537
+ catch {
1538
+ // Ignore malformed package metadata; normal package resolution can handle it.
1539
+ }
1540
+ }
1541
+ return aliases;
1542
+ }
1392
1543
  function aliasArrayFrom(alias) {
1393
1544
  if (!alias)
1394
1545
  return [];
@@ -1399,6 +1550,18 @@ function aliasArrayFrom(alias) {
1399
1550
  }
1400
1551
  return [];
1401
1552
  }
1553
+ const DEFAULT_VITE_WATCH_IGNORES = [
1554
+ "**/.git/**",
1555
+ "**/node_modules/**",
1556
+ "**/.react-router/**",
1557
+ "**/.generated/**",
1558
+ "**/.agents/**",
1559
+ "**/.claude/**",
1560
+ "**/changelog/**",
1561
+ "**/data/**",
1562
+ "**/dist/**",
1563
+ "**/build/**",
1564
+ ];
1402
1565
  function forceServeOnly(pluginOrPreset) {
1403
1566
  if (Array.isArray(pluginOrPreset))
1404
1567
  return pluginOrPreset.map(forceServeOnly);
@@ -1485,9 +1648,17 @@ function createAgentNativeConfig(options = {}, command, userConfig = {}) {
1485
1648
  const workspaceNodeModulesAllow = isWorkspaceChild
1486
1649
  ? [path.resolve(cwd, "../../node_modules")]
1487
1650
  : [];
1651
+ const packageWorkspaceRoot = workspaceRoot ?? findPnpmWorkspaceRoot(cwd);
1652
+ const localWorkspacePackageDeps = findLocalWorkspacePackageDeps(cwd, packageWorkspaceRoot);
1653
+ const localWorkspacePackageAllow = localWorkspacePackageDeps.map((pkg) => pkg.packageDir);
1654
+ const localWorkspacePackageResolveAliases = localWorkspacePackageAliases(localWorkspacePackageDeps);
1488
1655
  const workspaceCoreNoExternal = workspaceCore
1489
1656
  ? [new RegExp(`^${escapeRegex(workspaceCore.packageName)}(/.*)?$`)]
1490
1657
  : [];
1658
+ const localWorkspacePackageNoExternal = localWorkspacePackageDeps.map((pkg) => new RegExp(`^${escapeRegex(pkg.packageName)}(/.*)?$`));
1659
+ const forcePollingWatch = process.env.CHOKIDAR_USEPOLLING === "1";
1660
+ const pollingWatchInterval = Number(process.env.CHOKIDAR_INTERVAL ?? 1000);
1661
+ const userWatch = userConfig.server?.watch ?? {};
1491
1662
  return {
1492
1663
  logLevel: options.logLevel ??
1493
1664
  userConfig.logLevel ??
@@ -1515,6 +1686,21 @@ function createAgentNativeConfig(options = {}, command, userConfig = {}) {
1515
1686
  ".ngrok.io",
1516
1687
  ".trycloudflare.com",
1517
1688
  ],
1689
+ watch: {
1690
+ ...userWatch,
1691
+ ignored: [
1692
+ ...DEFAULT_VITE_WATCH_IGNORES,
1693
+ ...arrayFrom(userWatch?.ignored),
1694
+ ],
1695
+ ...(forcePollingWatch
1696
+ ? {
1697
+ usePolling: true,
1698
+ interval: Number.isFinite(pollingWatchInterval)
1699
+ ? pollingWatchInterval
1700
+ : 1000,
1701
+ }
1702
+ : {}),
1703
+ },
1518
1704
  fs: {
1519
1705
  ...(userConfig.server?.fs ?? {}),
1520
1706
  allow: [
@@ -1522,6 +1708,7 @@ function createAgentNativeConfig(options = {}, command, userConfig = {}) {
1522
1708
  ...monorepoCoreAllow,
1523
1709
  ...monorepoNodeModulesAllow,
1524
1710
  ...workspaceCoreFsAllow,
1711
+ ...localWorkspacePackageAllow,
1525
1712
  ...workspaceNodeModulesAllow,
1526
1713
  ...(userConfig.server?.fs?.allow ?? []),
1527
1714
  ...(options.fsAllow ?? []),
@@ -1597,6 +1784,7 @@ function createAgentNativeConfig(options = {}, command, userConfig = {}) {
1597
1784
  ? [/^@agent-native\/scheduling(\/.*)?$/]
1598
1785
  : []),
1599
1786
  ...workspaceCoreNoExternal,
1787
+ ...localWorkspacePackageNoExternal,
1600
1788
  ...arrayFrom(userConfig.ssr?.noExternal),
1601
1789
  ],
1602
1790
  external: [
@@ -1646,6 +1834,7 @@ function createAgentNativeConfig(options = {}, command, userConfig = {}) {
1646
1834
  // Uses regex with $ anchor for exact matching to prevent
1647
1835
  // @agent-native/core from prefix-matching @agent-native/core/client.
1648
1836
  ...getCoreSourceAliases(cwd),
1837
+ ...localWorkspacePackageResolveAliases,
1649
1838
  // Standard path aliases (prefix matching is fine here)
1650
1839
  { find: "@", replacement: path.resolve(cwd, "./app") },
1651
1840
  { find: "@shared", replacement: path.resolve(cwd, "./shared") },