@agentuity/cli 1.0.59 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.ts +2 -3
- package/dist/cmd/build/app-config-extractor.d.ts +27 -0
- package/dist/cmd/build/app-config-extractor.d.ts.map +1 -0
- package/dist/cmd/build/app-config-extractor.js +152 -0
- package/dist/cmd/build/app-config-extractor.js.map +1 -0
- package/dist/cmd/build/app-router-detector.d.ts +2 -5
- package/dist/cmd/build/app-router-detector.d.ts.map +1 -1
- package/dist/cmd/build/app-router-detector.js +130 -154
- package/dist/cmd/build/app-router-detector.js.map +1 -1
- package/dist/cmd/build/ci.d.ts.map +1 -1
- package/dist/cmd/build/ci.js +5 -21
- package/dist/cmd/build/ci.js.map +1 -1
- package/dist/cmd/build/ids.d.ts +11 -0
- package/dist/cmd/build/ids.d.ts.map +1 -0
- package/dist/cmd/build/ids.js +18 -0
- package/dist/cmd/build/ids.js.map +1 -0
- package/dist/cmd/build/index.d.ts.map +1 -1
- package/dist/cmd/build/index.js +8 -0
- package/dist/cmd/build/index.js.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.d.ts +8 -4
- package/dist/cmd/build/vite/agent-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/agent-discovery.js +166 -487
- package/dist/cmd/build/vite/agent-discovery.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts +43 -14
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +290 -129
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/build/vite/config-loader.d.ts +15 -20
- package/dist/cmd/build/vite/config-loader.d.ts.map +1 -1
- package/dist/cmd/build/vite/config-loader.js +41 -74
- package/dist/cmd/build/vite/config-loader.js.map +1 -1
- package/dist/cmd/build/vite/docs-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/docs-generator.js +0 -2
- package/dist/cmd/build/vite/docs-generator.js.map +1 -1
- package/dist/cmd/build/vite/index.d.ts.map +1 -1
- package/dist/cmd/build/vite/index.js +0 -36
- package/dist/cmd/build/vite/index.js.map +1 -1
- package/dist/cmd/build/vite/lifecycle-generator.d.ts +10 -2
- package/dist/cmd/build/vite/lifecycle-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/lifecycle-generator.js +302 -23
- package/dist/cmd/build/vite/lifecycle-generator.js.map +1 -1
- package/dist/cmd/build/vite/route-discovery.d.ts +11 -38
- package/dist/cmd/build/vite/route-discovery.d.ts.map +1 -1
- package/dist/cmd/build/vite/route-discovery.js +97 -177
- package/dist/cmd/build/vite/route-discovery.js.map +1 -1
- package/dist/cmd/build/vite/server-bundler.js +1 -1
- package/dist/cmd/build/vite/server-bundler.js.map +1 -1
- package/dist/cmd/build/vite/static-renderer.d.ts +0 -2
- package/dist/cmd/build/vite/static-renderer.d.ts.map +1 -1
- package/dist/cmd/build/vite/static-renderer.js +19 -13
- package/dist/cmd/build/vite/static-renderer.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.d.ts +6 -3
- package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server-config.js +175 -69
- package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.d.ts +8 -3
- package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-asset-server.js +14 -13
- package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +42 -190
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/build/vite/ws-proxy.d.ts +53 -0
- package/dist/cmd/build/vite/ws-proxy.d.ts.map +1 -0
- package/dist/cmd/build/vite/ws-proxy.js +95 -0
- package/dist/cmd/build/vite/ws-proxy.js.map +1 -0
- package/dist/cmd/build/vite-bundler.d.ts.map +1 -1
- package/dist/cmd/build/vite-bundler.js +0 -3
- package/dist/cmd/build/vite-bundler.js.map +1 -1
- package/dist/cmd/cloud/deploy-fork.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy-fork.js +15 -36
- package/dist/cmd/cloud/deploy-fork.js.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +28 -86
- package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
- package/dist/cmd/cloud/sandbox/run.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/run.js +2 -9
- package/dist/cmd/cloud/sandbox/run.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.js +2 -2
- package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
- package/dist/cmd/coder/hub-url.d.ts.map +1 -1
- package/dist/cmd/coder/hub-url.js +1 -3
- package/dist/cmd/coder/hub-url.js.map +1 -1
- package/dist/cmd/coder/start.js +6 -6
- package/dist/cmd/coder/start.js.map +1 -1
- package/dist/cmd/coder/tui-init.d.ts +2 -2
- package/dist/cmd/coder/tui-init.js +2 -2
- package/dist/cmd/coder/tui-init.js.map +1 -1
- package/dist/cmd/dev/file-watcher.d.ts.map +1 -1
- package/dist/cmd/dev/file-watcher.js +2 -8
- package/dist/cmd/dev/file-watcher.js.map +1 -1
- package/dist/cmd/dev/index.d.ts.map +1 -1
- package/dist/cmd/dev/index.js +432 -752
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/dev/process-manager.d.ts +104 -0
- package/dist/cmd/dev/process-manager.d.ts.map +1 -0
- package/dist/cmd/dev/process-manager.js +204 -0
- package/dist/cmd/dev/process-manager.js.map +1 -0
- package/dist/errors.d.ts +10 -24
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +12 -42
- package/dist/errors.js.map +1 -1
- package/dist/schema-generator.d.ts.map +1 -1
- package/dist/schema-generator.js +12 -2
- package/dist/schema-generator.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +5 -19
- package/dist/tui.js.map +1 -1
- package/dist/utils/version-mismatch.d.ts +39 -0
- package/dist/utils/version-mismatch.d.ts.map +1 -0
- package/dist/utils/version-mismatch.js +161 -0
- package/dist/utils/version-mismatch.js.map +1 -0
- package/package.json +6 -6
- package/src/cmd/ai/prompt/agent.md +0 -1
- package/src/cmd/ai/prompt/api.md +0 -7
- package/src/cmd/ai/prompt/web.md +51 -213
- package/src/cmd/build/app-config-extractor.ts +186 -0
- package/src/cmd/build/app-router-detector.ts +152 -182
- package/src/cmd/build/ci.ts +5 -21
- package/src/cmd/build/ids.ts +19 -0
- package/src/cmd/build/index.ts +10 -0
- package/src/cmd/build/vite/agent-discovery.ts +208 -679
- package/src/cmd/build/vite/bun-dev-server.ts +383 -146
- package/src/cmd/build/vite/config-loader.ts +45 -77
- package/src/cmd/build/vite/docs-generator.ts +0 -2
- package/src/cmd/build/vite/index.ts +1 -42
- package/src/cmd/build/vite/lifecycle-generator.ts +345 -21
- package/src/cmd/build/vite/route-discovery.ts +116 -274
- package/src/cmd/build/vite/server-bundler.ts +1 -1
- package/src/cmd/build/vite/static-renderer.ts +23 -15
- package/src/cmd/build/vite/vite-asset-server-config.ts +200 -70
- package/src/cmd/build/vite/vite-asset-server.ts +25 -15
- package/src/cmd/build/vite/vite-builder.ts +49 -220
- package/src/cmd/build/vite/ws-proxy.ts +126 -0
- package/src/cmd/build/vite-bundler.ts +0 -4
- package/src/cmd/cloud/deploy-fork.ts +16 -39
- package/src/cmd/cloud/sandbox/exec.ts +23 -130
- package/src/cmd/cloud/sandbox/run.ts +2 -9
- package/src/cmd/cloud/sandbox/snapshot/build.ts +2 -2
- package/src/cmd/coder/hub-url.ts +1 -3
- package/src/cmd/coder/start.ts +6 -6
- package/src/cmd/coder/tui-init.ts +4 -4
- package/src/cmd/dev/file-watcher.ts +2 -9
- package/src/cmd/dev/index.ts +476 -859
- package/src/cmd/dev/process-manager.ts +261 -0
- package/src/errors.ts +12 -44
- package/src/schema-generator.ts +12 -2
- package/src/tui.ts +5 -18
- package/src/utils/version-mismatch.ts +204 -0
- package/dist/cmd/build/ast.d.ts +0 -78
- package/dist/cmd/build/ast.d.ts.map +0 -1
- package/dist/cmd/build/ast.js +0 -2703
- package/dist/cmd/build/ast.js.map +0 -1
- package/dist/cmd/build/entry-generator.d.ts +0 -25
- package/dist/cmd/build/entry-generator.d.ts.map +0 -1
- package/dist/cmd/build/entry-generator.js +0 -695
- package/dist/cmd/build/entry-generator.js.map +0 -1
- package/dist/cmd/build/vite/api-mount-path.d.ts +0 -61
- package/dist/cmd/build/vite/api-mount-path.d.ts.map +0 -1
- package/dist/cmd/build/vite/api-mount-path.js +0 -83
- package/dist/cmd/build/vite/api-mount-path.js.map +0 -1
- package/dist/cmd/build/vite/registry-generator.d.ts +0 -19
- package/dist/cmd/build/vite/registry-generator.d.ts.map +0 -1
- package/dist/cmd/build/vite/registry-generator.js +0 -1108
- package/dist/cmd/build/vite/registry-generator.js.map +0 -1
- package/dist/cmd/build/webanalytics-generator.d.ts +0 -16
- package/dist/cmd/build/webanalytics-generator.d.ts.map +0 -1
- package/dist/cmd/build/webanalytics-generator.js +0 -178
- package/dist/cmd/build/webanalytics-generator.js.map +0 -1
- package/dist/cmd/build/workbench.d.ts +0 -7
- package/dist/cmd/build/workbench.d.ts.map +0 -1
- package/dist/cmd/build/workbench.js +0 -55
- package/dist/cmd/build/workbench.js.map +0 -1
- package/dist/utils/route-migration.d.ts +0 -62
- package/dist/utils/route-migration.d.ts.map +0 -1
- package/dist/utils/route-migration.js +0 -630
- package/dist/utils/route-migration.js.map +0 -1
- package/dist/utils/stream-capture.d.ts +0 -9
- package/dist/utils/stream-capture.d.ts.map +0 -1
- package/dist/utils/stream-capture.js +0 -34
- package/dist/utils/stream-capture.js.map +0 -1
- package/src/cmd/build/ast.ts +0 -3529
- package/src/cmd/build/entry-generator.ts +0 -760
- package/src/cmd/build/vite/api-mount-path.ts +0 -87
- package/src/cmd/build/vite/registry-generator.ts +0 -1267
- package/src/cmd/build/webanalytics-generator.ts +0 -197
- package/src/cmd/build/workbench.ts +0 -58
- package/src/utils/route-migration.ts +0 -757
- package/src/utils/stream-capture.ts +0 -39
|
@@ -5,48 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { join } from 'node:path';
|
|
8
|
-
import { existsSync,
|
|
9
|
-
import {
|
|
10
|
-
import type { InlineConfig, Plugin } from 'vite';
|
|
8
|
+
import { existsSync, rmSync } from 'node:fs';
|
|
9
|
+
import type { InlineConfig } from 'vite';
|
|
11
10
|
import type { Logger, DeployOptions } from '../../../types';
|
|
12
|
-
import { browserEnvPlugin } from './browser-env-plugin';
|
|
13
|
-
import { tailwindSourcePlugin } from './tailwind-source-plugin';
|
|
14
|
-
import { beaconPlugin } from './beacon-plugin';
|
|
15
|
-
import { publicAssetPathPlugin } from './public-asset-path-plugin';
|
|
16
11
|
import type { BuildReportCollector } from '../../../build-report';
|
|
17
12
|
|
|
18
|
-
/**
|
|
19
|
-
* Vite plugin to flatten the output structure for index.html
|
|
20
|
-
*
|
|
21
|
-
* When root is set to the project root (for TanStack Router compatibility),
|
|
22
|
-
* Vite outputs index.html to .agentuity/client/src/web/index.html instead of
|
|
23
|
-
* .agentuity/client/index.html. This plugin moves it to the expected location.
|
|
24
|
-
*/
|
|
25
|
-
function flattenHtmlOutputPlugin(outDir: string): Plugin {
|
|
26
|
-
return {
|
|
27
|
-
name: 'agentuity:flatten-html-output',
|
|
28
|
-
apply: 'build',
|
|
29
|
-
closeBundle() {
|
|
30
|
-
const nestedHtmlPath = join(outDir, 'src', 'web', 'index.html');
|
|
31
|
-
const targetHtmlPath = join(outDir, 'index.html');
|
|
32
|
-
|
|
33
|
-
if (existsSync(nestedHtmlPath)) {
|
|
34
|
-
renameSync(nestedHtmlPath, targetHtmlPath);
|
|
35
|
-
|
|
36
|
-
// Clean up empty src/web directory structure
|
|
37
|
-
const srcWebDir = join(outDir, 'src', 'web');
|
|
38
|
-
const srcDir = join(outDir, 'src');
|
|
39
|
-
try {
|
|
40
|
-
rmSync(srcWebDir, { recursive: true, force: true });
|
|
41
|
-
rmSync(srcDir, { recursive: true, force: true });
|
|
42
|
-
} catch {
|
|
43
|
-
// Ignore cleanup errors
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
|
|
50
13
|
export interface ViteBuildOptions {
|
|
51
14
|
rootDir: string;
|
|
52
15
|
mode: 'client' | 'server' | 'workbench';
|
|
@@ -75,25 +38,7 @@ export interface ViteBuildOptions {
|
|
|
75
38
|
* Uses inline Vite config (customizable via agentuity.config.ts)
|
|
76
39
|
*/
|
|
77
40
|
export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
|
|
78
|
-
const {
|
|
79
|
-
rootDir,
|
|
80
|
-
mode,
|
|
81
|
-
dev = false,
|
|
82
|
-
projectId = '',
|
|
83
|
-
deploymentId = '',
|
|
84
|
-
logger,
|
|
85
|
-
profile,
|
|
86
|
-
} = options;
|
|
87
|
-
|
|
88
|
-
const isViteDebug =
|
|
89
|
-
process.env.AGENTUITY_VITE_DEBUG === '1' || process.env.AGENTUITY_VITE_DEBUG === 'true';
|
|
90
|
-
if (isViteDebug) {
|
|
91
|
-
logger.debug('Vite debug logging enabled via AGENTUITY_VITE_DEBUG');
|
|
92
|
-
const existing = process.env.DEBUG || '';
|
|
93
|
-
if (!existing.includes('vite:')) {
|
|
94
|
-
process.env.DEBUG = existing ? `${existing},vite:*` : 'vite:*';
|
|
95
|
-
}
|
|
96
|
-
}
|
|
41
|
+
const { rootDir, mode, dev = false, logger, profile } = options;
|
|
97
42
|
|
|
98
43
|
logger.debug(`Running Vite build for mode: ${mode}`);
|
|
99
44
|
|
|
@@ -126,24 +71,7 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
|
|
|
126
71
|
profile,
|
|
127
72
|
});
|
|
128
73
|
|
|
129
|
-
//
|
|
130
|
-
const { loadAgentuityConfig, getWorkbenchConfig } = await import('./config-loader');
|
|
131
|
-
const config = await loadAgentuityConfig(rootDir, logger);
|
|
132
|
-
const workbenchConfig = getWorkbenchConfig(config, dev);
|
|
133
|
-
|
|
134
|
-
// Then, generate the entry file
|
|
135
|
-
const { generateEntryFile } = await import('../entry-generator');
|
|
136
|
-
await generateEntryFile({
|
|
137
|
-
rootDir,
|
|
138
|
-
projectId,
|
|
139
|
-
deploymentId: deploymentId || '',
|
|
140
|
-
logger,
|
|
141
|
-
mode: dev ? 'dev' : 'prod',
|
|
142
|
-
workbench: workbenchConfig.configured ? workbenchConfig : undefined,
|
|
143
|
-
analytics: config?.analytics,
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// Finally, build with Bun.build
|
|
74
|
+
// Build with Bun.build (app.ts is the entrypoint)
|
|
147
75
|
const { installExternalsAndBuild } = await import('./server-bundler');
|
|
148
76
|
await installExternalsAndBuild({
|
|
149
77
|
rootDir,
|
|
@@ -153,137 +81,56 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
|
|
|
153
81
|
return;
|
|
154
82
|
}
|
|
155
83
|
|
|
156
|
-
// Dynamically import vite
|
|
157
|
-
|
|
158
|
-
const projectRequire = createRequire(join(rootDir, 'package.json'));
|
|
159
|
-
let vitePath = 'vite';
|
|
160
|
-
let reactPluginPath = '@vitejs/plugin-react';
|
|
161
|
-
try {
|
|
162
|
-
vitePath = projectRequire.resolve('vite');
|
|
163
|
-
reactPluginPath = projectRequire.resolve('@vitejs/plugin-react');
|
|
164
|
-
} catch {
|
|
165
|
-
// Project doesn't have vite, use CLI's bundled version
|
|
166
|
-
}
|
|
167
|
-
const { build: viteBuild } = await import(vitePath);
|
|
168
|
-
const reactModule = await import(reactPluginPath);
|
|
169
|
-
const react = reactModule.default;
|
|
84
|
+
// Dynamically import vite for workbench builds
|
|
85
|
+
const { build: viteBuild } = await import('vite');
|
|
170
86
|
|
|
171
|
-
// For client/workbench, use inline config
|
|
87
|
+
// For client/workbench, use inline config with vite.config.ts loading
|
|
172
88
|
let viteConfig: InlineConfig;
|
|
173
89
|
|
|
174
90
|
if (mode === 'client') {
|
|
175
|
-
//
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
//
|
|
179
|
-
const
|
|
180
|
-
workbenchEnabled = false,
|
|
181
|
-
workbenchRoute = '/workbench',
|
|
182
|
-
analyticsEnabled = false,
|
|
183
|
-
} = options;
|
|
184
|
-
|
|
185
|
-
// Determine CDN base URL for production builds
|
|
186
|
-
// Use CDN for all non-dev builds with a deploymentId (including local region)
|
|
187
|
-
const isLocalRegion = options.region === 'local';
|
|
188
|
-
const cdnDomain = isLocalRegion
|
|
189
|
-
? 'localstack-static-assets.t3.storageapi.dev'
|
|
190
|
-
: 'cdn.agentuity.com';
|
|
191
|
-
const cdnBaseUrl =
|
|
192
|
-
!dev && deploymentId ? `https://${cdnDomain}/${deploymentId}/client/` : undefined;
|
|
193
|
-
|
|
194
|
-
// Load custom user plugins from agentuity.config.ts if it exists
|
|
91
|
+
// For client builds, spawn vite as a subprocess.
|
|
92
|
+
// This avoids issues with Bun's module loading that cause problems
|
|
93
|
+
// with certain plugins like @sveltejs/vite-plugin-svelte.
|
|
94
|
+
// The vite.config.ts in the project handles all configuration.
|
|
95
|
+
const buildMode = dev ? 'development' : 'production';
|
|
195
96
|
const clientOutDir = join(rootDir, '.agentuity/client');
|
|
196
|
-
const { loadAgentuityConfig, hasFrameworkPlugin } = await import('./config-loader');
|
|
197
|
-
const userConfig = await loadAgentuityConfig(rootDir, logger);
|
|
198
|
-
const userPlugins = userConfig?.plugins || [];
|
|
199
|
-
|
|
200
|
-
// Auto-add React plugin if no framework plugin is present (backwards compatibility)
|
|
201
|
-
if (userPlugins.length === 0 || !hasFrameworkPlugin(userPlugins)) {
|
|
202
|
-
logger.debug(
|
|
203
|
-
'No framework plugin found in agentuity.config.ts plugins, adding React automatically'
|
|
204
|
-
);
|
|
205
|
-
userPlugins.unshift(react());
|
|
206
|
-
}
|
|
207
97
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
98
|
+
logger.debug('Spawning vite build for client (subprocess mode)');
|
|
99
|
+
logger.debug(' outDir: %s', clientOutDir);
|
|
100
|
+
logger.debug(' mode: %s', buildMode);
|
|
101
|
+
|
|
102
|
+
const viteProcess = Bun.spawn(
|
|
103
|
+
['bun', 'x', 'vite', 'build', '--mode', buildMode, '--outDir', clientOutDir],
|
|
104
|
+
{
|
|
105
|
+
cwd: rootDir,
|
|
106
|
+
stdout: 'inherit',
|
|
107
|
+
stderr: 'inherit',
|
|
108
|
+
}
|
|
109
|
+
);
|
|
211
110
|
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
// Fix incorrect public asset paths and rewrite to CDN URLs
|
|
217
|
-
publicAssetPathPlugin({ cdnBaseUrl }),
|
|
218
|
-
flattenHtmlOutputPlugin(clientOutDir),
|
|
219
|
-
// Emit analytics beacon as hashed CDN asset (prod builds only)
|
|
220
|
-
beaconPlugin({ enabled: analyticsEnabled && !dev }),
|
|
221
|
-
];
|
|
222
|
-
|
|
223
|
-
// Merge custom define values from user config
|
|
224
|
-
const userDefine = userConfig?.define || {};
|
|
225
|
-
if (Object.keys(userDefine).length > 0) {
|
|
226
|
-
logger.debug(
|
|
227
|
-
'Loaded %d custom define(s) from agentuity.config.ts',
|
|
228
|
-
Object.keys(userDefine).length
|
|
229
|
-
);
|
|
111
|
+
const exitCode = await viteProcess.exited;
|
|
112
|
+
|
|
113
|
+
if (exitCode !== 0) {
|
|
114
|
+
throw new Error(`Vite build exited with code ${exitCode}`);
|
|
230
115
|
}
|
|
231
116
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
// from the repo root, matching where agentuity.config.ts is located
|
|
235
|
-
root: rootDir,
|
|
236
|
-
plugins,
|
|
237
|
-
envPrefix: ['VITE_', 'AGENTUITY_PUBLIC_', 'PUBLIC_'],
|
|
238
|
-
publicDir: join(rootDir, 'src', 'web', 'public'),
|
|
239
|
-
base: cdnBaseUrl, // CDN URL for production assets
|
|
240
|
-
define: {
|
|
241
|
-
// Merge user-defined constants first
|
|
242
|
-
...userDefine,
|
|
243
|
-
// Then add default defines (these will override any user-defined protected keys)
|
|
244
|
-
// Set workbench path if enabled (use import.meta.env for client code)
|
|
245
|
-
'import.meta.env.AGENTUITY_PUBLIC_WORKBENCH_PATH': workbenchEnabled
|
|
246
|
-
? JSON.stringify(workbenchRoute)
|
|
247
|
-
: 'undefined',
|
|
248
|
-
},
|
|
249
|
-
build: {
|
|
250
|
-
outDir: clientOutDir,
|
|
251
|
-
rollupOptions: {
|
|
252
|
-
input: htmlPath,
|
|
253
|
-
},
|
|
254
|
-
manifest: true,
|
|
255
|
-
emptyOutDir: true,
|
|
256
|
-
// Copy public files to output for CDN upload (production builds only)
|
|
257
|
-
// In dev mode, Vite serves them directly from src/web/public/
|
|
258
|
-
copyPublicDir: !dev,
|
|
259
|
-
},
|
|
260
|
-
logLevel: isViteDebug ? 'info' : 'warn',
|
|
261
|
-
};
|
|
117
|
+
logger.debug('Vite build complete for mode: client');
|
|
118
|
+
return;
|
|
262
119
|
} else if (mode === 'workbench') {
|
|
263
120
|
const { workbenchRoute = '/workbench' } = options;
|
|
264
121
|
// Ensure route ends with / for Vite base
|
|
265
122
|
const base = workbenchRoute.endsWith('/') ? workbenchRoute : `${workbenchRoute}/`;
|
|
266
123
|
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
const
|
|
270
|
-
const
|
|
271
|
-
if (Object.keys(userDefine).length > 0) {
|
|
272
|
-
logger.debug(
|
|
273
|
-
'Loaded %d custom define(s) from agentuity.config.ts for workbench',
|
|
274
|
-
Object.keys(userDefine).length
|
|
275
|
-
);
|
|
276
|
-
}
|
|
124
|
+
// Workbench is built with React (internal UI)
|
|
125
|
+
// Use CLI's bundled React plugin since workbench is our code
|
|
126
|
+
const reactModule = await import('@vitejs/plugin-react');
|
|
127
|
+
const react = reactModule.default;
|
|
277
128
|
|
|
278
129
|
viteConfig = {
|
|
279
130
|
root: join(rootDir, '.agentuity/workbench-src'), // Use generated workbench source
|
|
280
131
|
base, // All workbench assets are under the configured route
|
|
281
132
|
plugins: [react()],
|
|
282
133
|
envPrefix: ['VITE_', 'AGENTUITY_PUBLIC_', 'PUBLIC_'],
|
|
283
|
-
define: {
|
|
284
|
-
// Merge user-defined constants
|
|
285
|
-
...userDefine,
|
|
286
|
-
},
|
|
287
134
|
build: {
|
|
288
135
|
outDir: join(rootDir, '.agentuity/workbench'),
|
|
289
136
|
rollupOptions: {
|
|
@@ -292,14 +139,13 @@ export async function runViteBuild(options: ViteBuildOptions): Promise<void> {
|
|
|
292
139
|
manifest: true,
|
|
293
140
|
emptyOutDir: true,
|
|
294
141
|
},
|
|
295
|
-
logLevel:
|
|
142
|
+
logLevel: 'warn',
|
|
296
143
|
};
|
|
297
144
|
} else {
|
|
298
145
|
throw new Error(`Unknown build mode: ${mode}`);
|
|
299
146
|
}
|
|
300
147
|
|
|
301
|
-
//
|
|
302
|
-
// Force the build to use the correct mode
|
|
148
|
+
// For workbench mode, use programmatic vite build
|
|
303
149
|
const buildMode = dev ? 'development' : 'production';
|
|
304
150
|
|
|
305
151
|
await viteBuild({
|
|
@@ -334,21 +180,11 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
|
|
|
334
180
|
static: { included: false, duration: 0, routes: 0 },
|
|
335
181
|
};
|
|
336
182
|
|
|
337
|
-
// Load config
|
|
338
|
-
const {
|
|
339
|
-
const
|
|
340
|
-
|
|
341
|
-
// Copy bundle files if configured (before build so build output takes priority)
|
|
342
|
-
if (config?.bundle?.length) {
|
|
343
|
-
const { copyBundleFiles } = await import('./bundle-files');
|
|
344
|
-
const outDir = join(rootDir, '.agentuity');
|
|
345
|
-
const count = await copyBundleFiles(rootDir, outDir, config.bundle, logger);
|
|
346
|
-
if (count > 0) {
|
|
347
|
-
logger.debug(`Copied ${count} bundle file(s) to .agentuity`);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
183
|
+
// Load runtime config from createApp() in app.ts (v2 approach)
|
|
184
|
+
const { getWorkbenchConfig, loadRuntimeConfig } = await import('./config-loader');
|
|
185
|
+
const runtimeConfig = await loadRuntimeConfig(rootDir, logger);
|
|
350
186
|
|
|
351
|
-
const workbenchConfig = getWorkbenchConfig(
|
|
187
|
+
const workbenchConfig = getWorkbenchConfig(dev, runtimeConfig);
|
|
352
188
|
// Generate workbench files BEFORE any builds if enabled (dev mode only)
|
|
353
189
|
if (workbenchConfig.enabled) {
|
|
354
190
|
logger.debug('Workbench enabled (dev mode), generating files before build...');
|
|
@@ -358,7 +194,6 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
|
|
|
358
194
|
|
|
359
195
|
// 1. Discover agents and routes BEFORE builds
|
|
360
196
|
logger.debug('Discovering agents and routes...');
|
|
361
|
-
const { generateAgentRegistry, generateRouteRegistry } = await import('./registry-generator');
|
|
362
197
|
const { discoverAgents } = await import('./agent-discovery');
|
|
363
198
|
const { discoverRoutes } = await import('./route-discovery');
|
|
364
199
|
|
|
@@ -369,24 +204,18 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
|
|
|
369
204
|
options.deploymentId || '',
|
|
370
205
|
logger
|
|
371
206
|
);
|
|
372
|
-
const { routes
|
|
373
|
-
srcDir,
|
|
374
|
-
projectId,
|
|
375
|
-
options.deploymentId || '',
|
|
376
|
-
logger
|
|
377
|
-
);
|
|
207
|
+
const { routes } = await discoverRoutes(srcDir, projectId, options.deploymentId || '', logger);
|
|
378
208
|
|
|
379
|
-
//
|
|
380
|
-
// (TypeScript needs these files to exist during type checking)
|
|
381
|
-
generateAgentRegistry(srcDir, agentMetadata);
|
|
382
|
-
await generateRouteRegistry(srcDir, routeInfoList);
|
|
383
|
-
logger.debug('Agent and route registries generated');
|
|
209
|
+
// Agent metadata is used for metadata.json generation (no registry codegen needed)
|
|
384
210
|
|
|
385
211
|
// Check if web frontend exists
|
|
386
212
|
const hasWebFrontend = await Bun.file(join(rootDir, 'src', 'web', 'index.html')).exists();
|
|
387
213
|
|
|
388
214
|
// Check if analytics is enabled
|
|
389
|
-
|
|
215
|
+
// v2: analytics config comes from createApp()
|
|
216
|
+
const analyticsFromRuntime = runtimeConfig?.analytics;
|
|
217
|
+
const analyticsEnabled =
|
|
218
|
+
analyticsFromRuntime !== undefined ? analyticsFromRuntime !== false : true;
|
|
390
219
|
|
|
391
220
|
// 2. Build client (only if web frontend exists)
|
|
392
221
|
if (hasWebFrontend) {
|
|
@@ -407,15 +236,15 @@ export async function runAllBuilds(options: Omit<ViteBuildOptions, 'mode'>): Pro
|
|
|
407
236
|
logger.debug('Skipping client build - no src/web/index.html found');
|
|
408
237
|
}
|
|
409
238
|
|
|
410
|
-
// 2b. Static rendering (if
|
|
411
|
-
|
|
239
|
+
// 2b. Static rendering (if entry-server.tsx exists)
|
|
240
|
+
const entryServerPath = join(rootDir, 'src', 'web', 'entry-server.tsx');
|
|
241
|
+
if (existsSync(entryServerPath) && hasWebFrontend) {
|
|
412
242
|
logger.debug('Running static rendering (pre-rendering all routes)...');
|
|
413
243
|
const endStaticDiagnostic = collector?.startDiagnostic('static-render');
|
|
414
244
|
const { runStaticRender } = await import('./static-renderer');
|
|
415
245
|
const staticResult = await runStaticRender({
|
|
416
246
|
rootDir,
|
|
417
247
|
logger,
|
|
418
|
-
userPlugins: config?.plugins || [],
|
|
419
248
|
});
|
|
420
249
|
result.static.included = true;
|
|
421
250
|
result.static.duration = staticResult.duration;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket-aware front-door TCP proxy for dev mode.
|
|
3
|
+
*
|
|
4
|
+
* Bun's node:http has several bugs that prevent Vite's built-in http-proxy
|
|
5
|
+
* from proxying WebSocket upgrades (see linked PRs). Rather than polyfilling
|
|
6
|
+
* those bugs, this module places a lightweight `net.createServer` on the
|
|
7
|
+
* user-facing port. It inspects the first bytes of each TCP connection and
|
|
8
|
+
* routes accordingly:
|
|
9
|
+
*
|
|
10
|
+
* - **WebSocket upgrades to backend paths** → piped directly to Bun backend
|
|
11
|
+
* (Bun's native `server.upgrade()` works perfectly over raw TCP)
|
|
12
|
+
* - **Everything else** (HTTP requests, Vite HMR WebSocket) → piped to Vite
|
|
13
|
+
*
|
|
14
|
+
* From the browser's perspective there is only one port. Vite and Bun both
|
|
15
|
+
* listen on internal ports that are never exposed.
|
|
16
|
+
*
|
|
17
|
+
* Bun bugs this works around:
|
|
18
|
+
* - https://github.com/oven-sh/bun/pull/27237 (socket.write drops data)
|
|
19
|
+
* - https://github.com/oven-sh/bun/pull/26264 (missing destroySoon)
|
|
20
|
+
* - https://github.com/oven-sh/bun/pull/27859 (http.request upgrade event)
|
|
21
|
+
* - Server-side upgrade socket read broken (HTTP parser doesn't hand off)
|
|
22
|
+
*
|
|
23
|
+
* This entire module can be removed once those Bun PRs are merged and the
|
|
24
|
+
* Vite `ws: true` proxy works natively under Bun.
|
|
25
|
+
*
|
|
26
|
+
* ```
|
|
27
|
+
* Browser ──TCP──▶ net.Server (:3500, user-facing)
|
|
28
|
+
* │
|
|
29
|
+
* ┌───────────┴───────────┐
|
|
30
|
+
* ▼ (WS upgrade to ▼ (everything else)
|
|
31
|
+
* backend paths)
|
|
32
|
+
* Bun backend (:3501) Vite server (:3502)
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import { createServer, connect, type Server } from 'node:net';
|
|
37
|
+
import type { Logger } from '../../../types';
|
|
38
|
+
|
|
39
|
+
export interface WsProxyOptions {
|
|
40
|
+
/** Port the front-door proxy listens on (user-facing) */
|
|
41
|
+
port: number;
|
|
42
|
+
/** Port of the Vite dev server (internal) */
|
|
43
|
+
vitePort: number;
|
|
44
|
+
/** Port of the Bun backend server (internal) */
|
|
45
|
+
backendPort: number;
|
|
46
|
+
/** Route path prefixes that should be proxied to the backend */
|
|
47
|
+
routePaths: string[];
|
|
48
|
+
logger: Logger;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Start a front-door TCP proxy that routes WebSocket upgrades to the Bun
|
|
53
|
+
* backend and everything else to Vite. Returns the `net.Server` instance.
|
|
54
|
+
*/
|
|
55
|
+
export function startWsProxy(options: WsProxyOptions): Promise<Server> {
|
|
56
|
+
const { port, vitePort, backendPort, routePaths, logger } = options;
|
|
57
|
+
|
|
58
|
+
// Prefixes whose WebSocket upgrades go to Bun instead of Vite
|
|
59
|
+
const wsPathPrefixes = ['/_agentuity', ...routePaths];
|
|
60
|
+
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
const server = createServer((socket) => {
|
|
63
|
+
let handled = false;
|
|
64
|
+
|
|
65
|
+
// Peek at the first chunk to decide where to route
|
|
66
|
+
socket.once('data', (firstChunk) => {
|
|
67
|
+
handled = true;
|
|
68
|
+
|
|
69
|
+
const header = firstChunk.toString('utf8', 0, Math.min(firstChunk.length, 4096));
|
|
70
|
+
|
|
71
|
+
// Detect: is this a WebSocket upgrade for a backend path?
|
|
72
|
+
const isUpgrade = /upgrade:\s*websocket/i.test(header);
|
|
73
|
+
let targetPort = vitePort;
|
|
74
|
+
|
|
75
|
+
if (isUpgrade) {
|
|
76
|
+
const pathMatch = header.match(/^(?:GET|POST)\s+(\S+)/);
|
|
77
|
+
const pathname = (pathMatch?.[1] ?? '/').split('?')[0] ?? '/';
|
|
78
|
+
|
|
79
|
+
const isBackendPath = wsPathPrefixes.some(
|
|
80
|
+
(prefix) => pathname === prefix || pathname.startsWith(prefix + '/')
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (isBackendPath) {
|
|
84
|
+
targetPort = backendPort;
|
|
85
|
+
logger.debug('WS upgrade %s → Bun :%d', pathname, backendPort);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const target = connect(targetPort, '127.0.0.1');
|
|
90
|
+
|
|
91
|
+
target.on('connect', () => {
|
|
92
|
+
target.write(firstChunk);
|
|
93
|
+
socket.pipe(target);
|
|
94
|
+
target.pipe(socket);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
target.on('error', () => {
|
|
98
|
+
if (!socket.destroyed) socket.destroy();
|
|
99
|
+
});
|
|
100
|
+
socket.on('error', () => {
|
|
101
|
+
if (!target.destroyed) target.destroy();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Client disconnected before sending anything
|
|
106
|
+
socket.on('close', () => {
|
|
107
|
+
if (!handled) socket.destroy();
|
|
108
|
+
});
|
|
109
|
+
socket.on('error', () => {
|
|
110
|
+
if (!handled) socket.destroy();
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
server.on('error', reject);
|
|
115
|
+
|
|
116
|
+
server.listen(port, '127.0.0.1', () => {
|
|
117
|
+
logger.debug(
|
|
118
|
+
'WS front-door proxy on :%d (Vite :%d, Bun :%d)',
|
|
119
|
+
port,
|
|
120
|
+
vitePort,
|
|
121
|
+
backendPort
|
|
122
|
+
);
|
|
123
|
+
resolve(server);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
@@ -10,7 +10,6 @@ import { StructuredError } from '@agentuity/core';
|
|
|
10
10
|
import type { Logger, DeployOptions } from '../../types';
|
|
11
11
|
import { runAllBuilds } from './vite/vite-builder';
|
|
12
12
|
import { checkAndUpgradeDependencies } from '../../utils/dependency-checker';
|
|
13
|
-
import { promptRouteMigration } from '../../utils/route-migration';
|
|
14
13
|
import { checkBunVersion } from '../../utils/bun-version-checker';
|
|
15
14
|
import * as tui from '../../tui';
|
|
16
15
|
import type { BuildReportCollector } from '../../build-report';
|
|
@@ -90,9 +89,6 @@ export async function viteBundle(options: ViteBundleOptions): Promise<{ output:
|
|
|
90
89
|
});
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
// Check if project can migrate from file-based to explicit routing
|
|
94
|
-
await promptRouteMigration(rootDir, logger);
|
|
95
|
-
|
|
96
92
|
try {
|
|
97
93
|
// Run all builds (client -> workbench -> server)
|
|
98
94
|
logger.debug('Starting builds...');
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { spawn, type Subprocess } from 'bun';
|
|
14
14
|
import { tmpdir } from 'node:os';
|
|
15
15
|
import { join } from 'node:path';
|
|
16
|
-
import {
|
|
16
|
+
import { existsSync, readFileSync, unlinkSync } from 'node:fs';
|
|
17
17
|
import type { APIClient } from '../../api';
|
|
18
18
|
import { getUserAgent } from '../../api';
|
|
19
19
|
import { isUnicode } from '../../tui/symbols';
|
|
@@ -37,14 +37,12 @@ export interface ForkDeployResult {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* Stream data to a Pulse stream URL
|
|
41
|
-
* Accepts a string, Blob/BunFile, or ReadableStream as the body to avoid
|
|
42
|
-
* loading large outputs into memory.
|
|
40
|
+
* Stream data to a Pulse stream URL
|
|
43
41
|
*/
|
|
44
42
|
async function streamToPulse(
|
|
45
43
|
streamURL: string,
|
|
46
44
|
sdkKey: string,
|
|
47
|
-
data: string
|
|
45
|
+
data: string,
|
|
48
46
|
logger: Logger
|
|
49
47
|
): Promise<void> {
|
|
50
48
|
try {
|
|
@@ -76,8 +74,7 @@ export async function runForkedDeploy(options: ForkDeployOptions): Promise<ForkD
|
|
|
76
74
|
const buildLogsStreamURL = deployment.buildLogsStreamURL;
|
|
77
75
|
const reportFile = join(tmpdir(), `agentuity-deploy-${deploymentId}.json`);
|
|
78
76
|
const cleanLogsFile = join(tmpdir(), `agentuity-deploy-${deploymentId}-logs.txt`);
|
|
79
|
-
|
|
80
|
-
const rawLogsWriter = createWriteStream(rawLogsFile);
|
|
77
|
+
let outputBuffer = '';
|
|
81
78
|
let proc: Subprocess | null = null;
|
|
82
79
|
let cancelled = false;
|
|
83
80
|
|
|
@@ -198,6 +195,7 @@ export async function runForkedDeploy(options: ForkDeployOptions): Promise<ForkD
|
|
|
198
195
|
|
|
199
196
|
const handleOutput = async (stream: ReadableStream<Uint8Array>, isStderr: boolean) => {
|
|
200
197
|
const reader = stream.getReader();
|
|
198
|
+
const decoder = new TextDecoder();
|
|
201
199
|
const target = isStderr ? process.stderr : process.stdout;
|
|
202
200
|
|
|
203
201
|
try {
|
|
@@ -205,9 +203,8 @@ export async function runForkedDeploy(options: ForkDeployOptions): Promise<ForkD
|
|
|
205
203
|
const { done, value } = await reader.read();
|
|
206
204
|
if (done) break;
|
|
207
205
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
rawLogsWriter.write(value);
|
|
206
|
+
const text = decoder.decode(value, { stream: true });
|
|
207
|
+
outputBuffer += text;
|
|
211
208
|
target.write(value);
|
|
212
209
|
}
|
|
213
210
|
} catch (err) {
|
|
@@ -226,11 +223,6 @@ export async function runForkedDeploy(options: ForkDeployOptions): Promise<ForkD
|
|
|
226
223
|
|
|
227
224
|
await Promise.all([stdoutPromise, stderrPromise]);
|
|
228
225
|
|
|
229
|
-
// Close the raw logs writer so the file is fully flushed before reading
|
|
230
|
-
await new Promise<void>((resolve) => {
|
|
231
|
-
rawLogsWriter.end(resolve);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
226
|
const exitCode = await proc.exited;
|
|
235
227
|
logger.debug('Child process exited with code: %d', exitCode);
|
|
236
228
|
|
|
@@ -257,11 +249,12 @@ export async function runForkedDeploy(options: ForkDeployOptions): Promise<ForkD
|
|
|
257
249
|
logger.debug('Failed to read clean logs file: %s', err);
|
|
258
250
|
}
|
|
259
251
|
}
|
|
252
|
+
// Fall back to raw output if no clean logs
|
|
253
|
+
if (!logsContent && outputBuffer) {
|
|
254
|
+
logsContent = outputBuffer;
|
|
255
|
+
}
|
|
260
256
|
if (logsContent) {
|
|
261
257
|
await streamToPulse(buildLogsStreamURL, sdkKey, logsContent, logger);
|
|
262
|
-
} else if (existsSync(rawLogsFile)) {
|
|
263
|
-
// Stream raw logs file directly to Pulse without loading into memory
|
|
264
|
-
await streamToPulse(buildLogsStreamURL, sdkKey, Bun.file(rawLogsFile), logger);
|
|
265
258
|
}
|
|
266
259
|
}
|
|
267
260
|
|
|
@@ -314,27 +307,11 @@ export async function runForkedDeploy(options: ForkDeployOptions): Promise<ForkD
|
|
|
314
307
|
// ignore
|
|
315
308
|
}
|
|
316
309
|
}
|
|
317
|
-
if (logsContent) {
|
|
318
|
-
logsContent
|
|
319
|
-
await streamToPulse(buildLogsStreamURL, sdkKey, logsContent, logger);
|
|
320
|
-
} else {
|
|
321
|
-
// Append error to raw logs file and stream it without loading into memory
|
|
322
|
-
try {
|
|
323
|
-
appendFileSync(rawLogsFile, `\n\n--- FORK ERROR ---\n${errorMessage}\n`);
|
|
324
|
-
} catch {
|
|
325
|
-
// ignore — file may not exist if child never produced output
|
|
326
|
-
}
|
|
327
|
-
if (existsSync(rawLogsFile)) {
|
|
328
|
-
await streamToPulse(buildLogsStreamURL, sdkKey, Bun.file(rawLogsFile), logger);
|
|
329
|
-
} else {
|
|
330
|
-
await streamToPulse(
|
|
331
|
-
buildLogsStreamURL,
|
|
332
|
-
sdkKey,
|
|
333
|
-
`--- FORK ERROR ---\n${errorMessage}\n`,
|
|
334
|
-
logger
|
|
335
|
-
);
|
|
336
|
-
}
|
|
310
|
+
if (!logsContent) {
|
|
311
|
+
logsContent = outputBuffer;
|
|
337
312
|
}
|
|
313
|
+
logsContent += `\n\n--- FORK ERROR ---\n${errorMessage}\n`;
|
|
314
|
+
await streamToPulse(buildLogsStreamURL, sdkKey, logsContent, logger);
|
|
338
315
|
}
|
|
339
316
|
|
|
340
317
|
try {
|
|
@@ -383,7 +360,7 @@ export async function runForkedDeploy(options: ForkDeployOptions): Promise<ForkD
|
|
|
383
360
|
process.off('SIGTERM', sigtermHandler);
|
|
384
361
|
|
|
385
362
|
// Clean up temp files
|
|
386
|
-
for (const file of [reportFile, cleanLogsFile
|
|
363
|
+
for (const file of [reportFile, cleanLogsFile]) {
|
|
387
364
|
if (existsSync(file)) {
|
|
388
365
|
try {
|
|
389
366
|
unlinkSync(file);
|