@agentuity/cli 1.0.47 → 2.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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/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/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 +10 -16
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +67 -134
- package/dist/cmd/build/vite/bun-dev-server.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.map +1 -1
- package/dist/cmd/build/vite/static-renderer.js +1 -9
- 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 +171 -18
- 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 +6 -34
- 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/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 +369 -720
- package/dist/cmd/dev/index.js.map +1 -1
- package/package.json +6 -8
- 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-router-detector.ts +152 -182
- package/src/cmd/build/ids.ts +19 -0
- package/src/cmd/build/vite/agent-discovery.ts +208 -679
- package/src/cmd/build/vite/bun-dev-server.ts +78 -154
- 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 +1 -11
- package/src/cmd/build/vite/vite-asset-server-config.ts +196 -20
- package/src/cmd/build/vite/vite-asset-server.ts +25 -15
- package/src/cmd/build/vite/vite-builder.ts +6 -51
- package/src/cmd/build/vite/ws-proxy.ts +126 -0
- package/src/cmd/build/vite-bundler.ts +0 -4
- package/src/cmd/dev/file-watcher.ts +2 -9
- package/src/cmd/dev/index.ts +409 -832
- 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/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
|
@@ -1,695 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Vite-native entry file generator (v2 - clean architecture)
|
|
3
|
-
* Single source for both dev and prod with minimal differences
|
|
4
|
-
*/
|
|
5
|
-
import { join } from 'node:path';
|
|
6
|
-
import { discoverRoutes } from './vite/route-discovery';
|
|
7
|
-
import { generateWebAnalyticsFile } from './webanalytics-generator';
|
|
8
|
-
import { computeApiMountPath } from './vite/api-mount-path';
|
|
9
|
-
/**
|
|
10
|
-
* Generate entry file with clean Vite-native architecture
|
|
11
|
-
*/
|
|
12
|
-
export async function generateEntryFile(options) {
|
|
13
|
-
const { rootDir, projectId, deploymentId, logger, mode, workbench, analytics, vitePort, noBundle, preDiscoveredRoutes, } = options;
|
|
14
|
-
const srcDir = join(rootDir, 'src');
|
|
15
|
-
const generatedDir = join(srcDir, 'generated');
|
|
16
|
-
const entryPath = join(generatedDir, 'app.ts');
|
|
17
|
-
logger.trace(`Generating unified entry file (supports both dev and prod modes)...`);
|
|
18
|
-
// Check if analytics is enabled
|
|
19
|
-
const analyticsEnabled = analytics !== false;
|
|
20
|
-
// Generate web analytics files only if enabled
|
|
21
|
-
if (analyticsEnabled) {
|
|
22
|
-
await generateWebAnalyticsFile({ rootDir, logger, analytics });
|
|
23
|
-
}
|
|
24
|
-
// Use pre-discovered routes if available, otherwise discover them
|
|
25
|
-
const routeInfoList = preDiscoveredRoutes ??
|
|
26
|
-
(await discoverRoutes(srcDir, projectId, deploymentId, logger)).routeInfoList;
|
|
27
|
-
// Check for web and workbench
|
|
28
|
-
const hasWebFrontend = (await Bun.file(join(srcDir, 'web', 'index.html')).exists()) ||
|
|
29
|
-
(await Bun.file(join(srcDir, 'web', 'frontend.tsx')).exists());
|
|
30
|
-
// Workbench is configured at build time, but only enabled at runtime in dev mode
|
|
31
|
-
const hasWorkbenchConfig = !!workbench;
|
|
32
|
-
// Get unique route files that need to be imported (relative to src/)
|
|
33
|
-
const routeFiles = new Set();
|
|
34
|
-
for (const route of routeInfoList) {
|
|
35
|
-
if (route.filename) {
|
|
36
|
-
routeFiles.add(route.filename);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
// Generate imports
|
|
40
|
-
const runtimeImports = [
|
|
41
|
-
` createRouter,`,
|
|
42
|
-
` createBaseMiddleware,`,
|
|
43
|
-
` createCorsMiddleware,`,
|
|
44
|
-
` createOtelMiddleware,`,
|
|
45
|
-
` createAgentMiddleware,`,
|
|
46
|
-
` createCompressionMiddleware,`,
|
|
47
|
-
` getAppState,`,
|
|
48
|
-
` getAppConfig,`,
|
|
49
|
-
` getUserRouter,`,
|
|
50
|
-
` register,`,
|
|
51
|
-
` getSpanProcessors,`,
|
|
52
|
-
` createServices,`,
|
|
53
|
-
` runAgentSetups,`,
|
|
54
|
-
` getThreadProvider,`,
|
|
55
|
-
` getSessionProvider,`,
|
|
56
|
-
` setGlobalLogger,`,
|
|
57
|
-
` setGlobalTracer,`,
|
|
58
|
-
` setGlobalRouter,`,
|
|
59
|
-
` enableProcessExitProtection,`,
|
|
60
|
-
` hasWaitUntilPending,`,
|
|
61
|
-
` loadBuildMetadata,`,
|
|
62
|
-
` createWorkbenchRouter,`,
|
|
63
|
-
` bootstrapRuntimeEnv,`,
|
|
64
|
-
` patchBunS3ForStorageDev,`,
|
|
65
|
-
` runShutdown,`,
|
|
66
|
-
];
|
|
67
|
-
if (noBundle) {
|
|
68
|
-
runtimeImports.push(` applyDevPatches,`);
|
|
69
|
-
}
|
|
70
|
-
if (hasWebFrontend) {
|
|
71
|
-
runtimeImports.push(` mimeTypes,`);
|
|
72
|
-
}
|
|
73
|
-
const imports = [
|
|
74
|
-
`import { `,
|
|
75
|
-
...runtimeImports,
|
|
76
|
-
`} from '@agentuity/runtime';`,
|
|
77
|
-
`import type { Context } from 'hono';`,
|
|
78
|
-
`import { websocket${hasWebFrontend ? ', serveStatic' : ''} } from 'hono/bun';`,
|
|
79
|
-
hasWebFrontend ? `import { readFileSync, existsSync } from 'node:fs';` : '',
|
|
80
|
-
].filter(Boolean);
|
|
81
|
-
imports.push(`import { type LogLevel } from '@agentuity/core';`);
|
|
82
|
-
if (analyticsEnabled) {
|
|
83
|
-
imports.push(`import { injectAnalytics, registerAnalyticsRoutes } from './webanalytics.js';`);
|
|
84
|
-
imports.push(`import { analyticsConfig } from './analytics-config.js';`);
|
|
85
|
-
}
|
|
86
|
-
// Generate route mounting code for all discovered routes
|
|
87
|
-
// Sort route files for deterministic output
|
|
88
|
-
const sortedRouteFiles = [...routeFiles].sort();
|
|
89
|
-
const routeImportsAndMounts = [];
|
|
90
|
-
let routeIndex = 0;
|
|
91
|
-
for (const routeFile of sortedRouteFiles) {
|
|
92
|
-
// Normalize path separators for cross-platform compatibility (Windows uses backslashes)
|
|
93
|
-
const normalizedRouteFile = routeFile.replace(/\\/g, '/');
|
|
94
|
-
// Convert src/api/auth/route.ts -> auth/route
|
|
95
|
-
const relativePath = normalizedRouteFile.replace(/^src\/api\//, '').replace(/\.tsx?$/, '');
|
|
96
|
-
// Determine the mount path using the shared helper
|
|
97
|
-
// This ensures consistency with route type generation in ast.ts
|
|
98
|
-
const mountPath = computeApiMountPath(relativePath);
|
|
99
|
-
const importName = `router_${routeIndex++}`;
|
|
100
|
-
routeImportsAndMounts.push(`const { default: ${importName} } = await import('../api/${relativePath}.js');`);
|
|
101
|
-
routeImportsAndMounts.push(`app.route('${mountPath}', ${importName});`);
|
|
102
|
-
}
|
|
103
|
-
const apiMount = routeImportsAndMounts.length > 0
|
|
104
|
-
? `
|
|
105
|
-
// Apply middleware and mount API routes
|
|
106
|
-
// If user passed router(s) via createApp({ router }), mount those instead of discovered files
|
|
107
|
-
const __userMounts = getUserRouter();
|
|
108
|
-
if (__userMounts) {
|
|
109
|
-
for (const mount of __userMounts) {
|
|
110
|
-
// Apply Agentuity middleware (CORS, OTel, agent context) to each user-provided prefix
|
|
111
|
-
const prefix = mount.path.endsWith('/') ? mount.path + '*' : mount.path + '/*';
|
|
112
|
-
app.use(prefix, createCorsMiddleware());
|
|
113
|
-
app.use(prefix, createOtelMiddleware());
|
|
114
|
-
app.use(prefix, createAgentMiddleware(''));
|
|
115
|
-
app.route(mount.path, mount.router);
|
|
116
|
-
}
|
|
117
|
-
} else {
|
|
118
|
-
// File-based routing: apply middleware to /api/* and mount discovered route files
|
|
119
|
-
app.use('/api/*', createCorsMiddleware());
|
|
120
|
-
app.use('/api/*', createOtelMiddleware());
|
|
121
|
-
app.use('/api/*', createAgentMiddleware(''));
|
|
122
|
-
${routeImportsAndMounts.map((line) => `\t${line}`).join('\n')}
|
|
123
|
-
}
|
|
124
|
-
`
|
|
125
|
-
: '';
|
|
126
|
-
// Workbench API routes mounting
|
|
127
|
-
// Always mounted - these routes are needed for the cloud workbench to communicate with deployed agents
|
|
128
|
-
// Auth is handled by middleware inside the router (signature verification in production, no auth in development)
|
|
129
|
-
// The hasWorkbenchConfig flag only controls whether the local workbench UI is served
|
|
130
|
-
const workbenchApiMount = `
|
|
131
|
-
// Mount workbench API routes (/_agentuity/workbench/*)
|
|
132
|
-
// Always available for cloud workbench communication
|
|
133
|
-
// Auth is handled inside the router (signature verification in production)
|
|
134
|
-
const workbenchRouter = createWorkbenchRouter();
|
|
135
|
-
app.route('/', workbenchRouter);
|
|
136
|
-
|
|
137
|
-
// hasWorkbenchConfig controls whether the local workbench UI is served (dev mode only)
|
|
138
|
-
const hasWorkbenchConfig = ${hasWorkbenchConfig};
|
|
139
|
-
`;
|
|
140
|
-
// Asset proxy routes - Always generated, but only active at runtime when:
|
|
141
|
-
// - NODE_ENV !== 'production' (isDevelopment())
|
|
142
|
-
// - and process.env.VITE_PORT is set
|
|
143
|
-
const assetProxyRoutes = `
|
|
144
|
-
// Asset proxy routes - Development mode only (proxies to Vite asset server)
|
|
145
|
-
if (isDevelopment() && process.env.VITE_PORT) {
|
|
146
|
-
const VITE_ASSET_PORT = parseInt(process.env.VITE_PORT, 10);
|
|
147
|
-
|
|
148
|
-
const proxyToVite = async (c: Context, pathOverride?: string) => {
|
|
149
|
-
const targetPath = pathOverride ?? c.req.path;
|
|
150
|
-
const viteUrl = \`http://127.0.0.1:\${VITE_ASSET_PORT}\${targetPath}\`;
|
|
151
|
-
try {
|
|
152
|
-
otel.logger.debug(\`[Proxy] \${c.req.method} \${c.req.path} -> Vite:\${VITE_ASSET_PORT}\${targetPath}\`);
|
|
153
|
-
const res = await fetch(viteUrl, { signal: AbortSignal.timeout(10000) });
|
|
154
|
-
otel.logger.debug(\`[Proxy] \${c.req.path} -> \${res.status} (\${res.headers.get('content-type')})\`);
|
|
155
|
-
return new Response(res.body, {
|
|
156
|
-
status: res.status,
|
|
157
|
-
headers: res.headers,
|
|
158
|
-
});
|
|
159
|
-
} catch (err) {
|
|
160
|
-
if (err instanceof Error && err.name === 'TimeoutError') {
|
|
161
|
-
otel.logger.error(\`Vite proxy timeout: \${c.req.path}\`);
|
|
162
|
-
return c.text('Vite asset server timeout', 504);
|
|
163
|
-
}
|
|
164
|
-
otel.logger.error(\`Failed to proxy to Vite: \${c.req.path} - \${err instanceof Error ? err.message : String(err)}\`);
|
|
165
|
-
return c.text('Vite asset server error', 500);
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// HMR WebSocket proxy - enables hot reload through tunnels (*.agentuity.live)
|
|
170
|
-
// This proxies the Vite HMR WebSocket connection from the Bun server to Vite
|
|
171
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
172
|
-
const viteHmrWebsocket = (globalThis as any).__AGENTUITY_VITE_HMR_WEBSOCKET__ = {
|
|
173
|
-
// Map of client WebSocket -> Vite WebSocket
|
|
174
|
-
connections: new Map<WebSocket, WebSocket>(),
|
|
175
|
-
|
|
176
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
177
|
-
open(clientWs: any) {
|
|
178
|
-
// Get the query string from ws.data (set during upgrade)
|
|
179
|
-
const queryString = clientWs.data?.queryString || '';
|
|
180
|
-
const viteWsUrl = \`ws://127.0.0.1:\${VITE_ASSET_PORT}/__vite_hmr\${queryString}\`;
|
|
181
|
-
otel.logger.debug('[HMR Proxy] Client connected, opening connection to Vite at %s', viteWsUrl);
|
|
182
|
-
|
|
183
|
-
// Connect to Vite with the 'vite-hmr' subprotocol (required by Vite)
|
|
184
|
-
const viteWs = new WebSocket(viteWsUrl, ['vite-hmr']);
|
|
185
|
-
|
|
186
|
-
viteWs.onopen = () => {
|
|
187
|
-
otel.logger.debug('[HMR Proxy] Connected to Vite HMR server');
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
viteWs.onmessage = (event) => {
|
|
191
|
-
// Forward messages from Vite to client
|
|
192
|
-
if (clientWs.readyState === WebSocket.OPEN) {
|
|
193
|
-
clientWs.send(event.data);
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
viteWs.onerror = (error) => {
|
|
198
|
-
otel.logger.error('[HMR Proxy] Vite WebSocket error: %s', error);
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
viteWs.onclose = () => {
|
|
202
|
-
otel.logger.debug('[HMR Proxy] Vite WebSocket closed');
|
|
203
|
-
viteHmrWebsocket.connections.delete(clientWs);
|
|
204
|
-
if (clientWs.readyState === WebSocket.OPEN) {
|
|
205
|
-
clientWs.close();
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
viteHmrWebsocket.connections.set(clientWs, viteWs);
|
|
210
|
-
},
|
|
211
|
-
|
|
212
|
-
message(clientWs: WebSocket, message: string | Buffer) {
|
|
213
|
-
// Forward messages from client to Vite
|
|
214
|
-
const viteWs = viteHmrWebsocket.connections.get(clientWs);
|
|
215
|
-
if (viteWs && viteWs.readyState === WebSocket.OPEN) {
|
|
216
|
-
viteWs.send(message);
|
|
217
|
-
}
|
|
218
|
-
},
|
|
219
|
-
|
|
220
|
-
close(clientWs: WebSocket) {
|
|
221
|
-
otel.logger.debug('[HMR Proxy] Client WebSocket closed');
|
|
222
|
-
const viteWs = viteHmrWebsocket.connections.get(clientWs);
|
|
223
|
-
if (viteWs) {
|
|
224
|
-
viteWs.close();
|
|
225
|
-
viteHmrWebsocket.connections.delete(clientWs);
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
// Register HMR WebSocket route - must be before other routes
|
|
231
|
-
app.get('/__vite_hmr', (c: Context) => {
|
|
232
|
-
const upgradeHeader = c.req.header('upgrade');
|
|
233
|
-
if (upgradeHeader?.toLowerCase() === 'websocket') {
|
|
234
|
-
// Get the Bun server from context using Hono's pattern
|
|
235
|
-
// When app.fetch(req, server) is called, Hono stores server as c.env
|
|
236
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
237
|
-
const server = 'server' in (c.env as any) ? (c.env as any).server : c.env;
|
|
238
|
-
|
|
239
|
-
if (server?.upgrade) {
|
|
240
|
-
// Extract query string to forward to Vite (includes token parameter)
|
|
241
|
-
const url = new URL(c.req.url);
|
|
242
|
-
const queryString = url.search; // Includes the '?' prefix
|
|
243
|
-
|
|
244
|
-
const success = server.upgrade(c.req.raw, {
|
|
245
|
-
data: { type: 'vite-hmr', queryString },
|
|
246
|
-
});
|
|
247
|
-
if (success) {
|
|
248
|
-
otel.logger.debug('[HMR Proxy] WebSocket upgrade successful');
|
|
249
|
-
return new Response(null);
|
|
250
|
-
}
|
|
251
|
-
otel.logger.error('[HMR Proxy] WebSocket upgrade returned false');
|
|
252
|
-
} else {
|
|
253
|
-
otel.logger.error('[HMR Proxy] Server upgrade method not available. c.env type: %s, keys: %s',
|
|
254
|
-
typeof c.env,
|
|
255
|
-
Object.keys(c.env || {}).join(', '));
|
|
256
|
-
}
|
|
257
|
-
return c.text('WebSocket upgrade failed', 500);
|
|
258
|
-
}
|
|
259
|
-
// Non-WebSocket request to HMR endpoint - proxy to Vite
|
|
260
|
-
return proxyToVite(c);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
// Vite client scripts and HMR
|
|
264
|
-
app.get('/@vite/*', (c: Context) => proxyToVite(c));
|
|
265
|
-
app.get('/@react-refresh', (c: Context) => proxyToVite(c));
|
|
266
|
-
|
|
267
|
-
// Source files for HMR
|
|
268
|
-
app.get('/src/web/*', (c: Context) => proxyToVite(c));
|
|
269
|
-
app.get('/src/*', (c: Context) => proxyToVite(c)); // Catch-all for other source files
|
|
270
|
-
|
|
271
|
-
// Workbench source files (in .agentuity/workbench-src/)
|
|
272
|
-
app.get('/.agentuity/workbench-src/*', (c: Context) => proxyToVite(c));
|
|
273
|
-
|
|
274
|
-
// Node modules (Vite transforms these)
|
|
275
|
-
app.get('/node_modules/*', (c: Context) => proxyToVite(c));
|
|
276
|
-
|
|
277
|
-
// Scoped packages (e.g., @agentuity/*, @types/*)
|
|
278
|
-
app.get('/@*', (c: Context) => proxyToVite(c));
|
|
279
|
-
|
|
280
|
-
// File system access (for Vite's @fs protocol)
|
|
281
|
-
app.get('/@fs/*', (c: Context) => proxyToVite(c));
|
|
282
|
-
|
|
283
|
-
// Module resolution (for Vite's @id protocol)
|
|
284
|
-
app.get('/@id/*', (c: Context) => proxyToVite(c));
|
|
285
|
-
|
|
286
|
-
// Static assets - Vite serves src/web/public/* at root, but code uses /public/* paths
|
|
287
|
-
// In production, the plugin transforms /public/foo.svg to CDN URLs
|
|
288
|
-
// Rewrite /public/foo.svg -> /foo.svg before proxying to Vite
|
|
289
|
-
app.get('/public/*', (c: Context) => {
|
|
290
|
-
const rootPath = c.req.path.replace(/^\\/public/, '');
|
|
291
|
-
return proxyToVite(c, rootPath);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
// Any .js, .jsx, .ts, .tsx files (catch remaining modules)
|
|
295
|
-
app.get('/*.js', (c: Context) => proxyToVite(c));
|
|
296
|
-
app.get('/*.jsx', (c: Context) => proxyToVite(c));
|
|
297
|
-
app.get('/*.ts', (c: Context) => proxyToVite(c));
|
|
298
|
-
app.get('/*.tsx', (c: Context) => proxyToVite(c));
|
|
299
|
-
app.get('/*.css', (c: Context) => proxyToVite(c));
|
|
300
|
-
}
|
|
301
|
-
`;
|
|
302
|
-
// Runtime mode detection helper (defined at top level for reuse)
|
|
303
|
-
// Dynamic property access prevents Bun.build from inlining NODE_ENV at build time
|
|
304
|
-
const modeDetection = `
|
|
305
|
-
// Runtime mode detection helper
|
|
306
|
-
// Dynamic string concatenation prevents Bun.build from inlining NODE_ENV at build time
|
|
307
|
-
// See: https://github.com/oven-sh/bun/issues/20183
|
|
308
|
-
const getEnv = (key: string) => process.env[key];
|
|
309
|
-
const isDevelopment = () => getEnv('NODE' + '_' + 'ENV') !== 'production';
|
|
310
|
-
`;
|
|
311
|
-
// Web routes (runtime mode detection)
|
|
312
|
-
let webRoutes = '';
|
|
313
|
-
if (hasWebFrontend) {
|
|
314
|
-
webRoutes = `
|
|
315
|
-
// Web routes - Runtime mode detection (dev proxies to Vite, prod serves static)
|
|
316
|
-
// Note: Session/thread cookies are set by /_agentuity/webanalytics/session.js (loaded via script tag)
|
|
317
|
-
// This keeps the HTML response static and cacheable
|
|
318
|
-
|
|
319
|
-
if (isDevelopment()) {
|
|
320
|
-
// Development mode: Proxy HTML from Vite to enable React Fast Refresh
|
|
321
|
-
const VITE_ASSET_PORT = parseInt(process.env.VITE_PORT || '${vitePort || 5173}', 10);
|
|
322
|
-
|
|
323
|
-
const devHtmlHandler = async (c: Context) => {
|
|
324
|
-
const viteUrl = \`http://127.0.0.1:\${VITE_ASSET_PORT}/src/web/index.html\`;
|
|
325
|
-
|
|
326
|
-
try {
|
|
327
|
-
otel.logger.debug('[Proxy] GET /src/web/index.html -> Vite:%d', VITE_ASSET_PORT);
|
|
328
|
-
const res = await fetch(viteUrl, { signal: AbortSignal.timeout(10000) });
|
|
329
|
-
|
|
330
|
-
// Get HTML text and transform relative paths to absolute
|
|
331
|
-
let html = await res.text();
|
|
332
|
-
html = html
|
|
333
|
-
.replace(/src="\\.\\//g, 'src="/src/web/')
|
|
334
|
-
.replace(/href="\\.\\//g, 'href="/src/web/');
|
|
335
|
-
|
|
336
|
-
${analyticsEnabled
|
|
337
|
-
? ` // Inject analytics config and script (session/thread read from cookies by beacon)
|
|
338
|
-
html = injectAnalytics(html, analyticsConfig);`
|
|
339
|
-
: ''}
|
|
340
|
-
|
|
341
|
-
return new Response(html, {
|
|
342
|
-
status: res.status,
|
|
343
|
-
headers: res.headers,
|
|
344
|
-
});
|
|
345
|
-
} catch (err) {
|
|
346
|
-
otel.logger.error('Failed to proxy HTML to Vite: %s', err instanceof Error ? err.message : String(err));
|
|
347
|
-
return c.text('Vite asset server error (HTML)', 500);
|
|
348
|
-
}
|
|
349
|
-
};
|
|
350
|
-
|
|
351
|
-
app.get('/', devHtmlHandler);
|
|
352
|
-
|
|
353
|
-
// 404 for unmatched API/system routes
|
|
354
|
-
app.all('/_agentuity/*', (c: Context) => c.notFound());
|
|
355
|
-
app.all('/api/*', (c: Context) => c.notFound());
|
|
356
|
-
if (!(hasWorkbenchConfig && isDevelopment())) {
|
|
357
|
-
app.all('/workbench/*', (c: Context) => c.notFound());
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// SPA fallback - serve index.html for client-side routing
|
|
361
|
-
app.get('*', async (c: Context) => {
|
|
362
|
-
const path = c.req.path;
|
|
363
|
-
// If path has a file extension, try proxying to Vite first (serves public files like robots.txt, llms.txt)
|
|
364
|
-
// Fall back to 404 if Vite also returns 404
|
|
365
|
-
if (/\\.[a-zA-Z0-9]+$/.test(path)) {
|
|
366
|
-
try {
|
|
367
|
-
const viteUrl = \`http://127.0.0.1:\${VITE_ASSET_PORT}\${path}\`;
|
|
368
|
-
const res = await fetch(viteUrl, { signal: AbortSignal.timeout(10000) });
|
|
369
|
-
if (res.status !== 404) {
|
|
370
|
-
return new Response(res.body, { status: res.status, headers: res.headers });
|
|
371
|
-
}
|
|
372
|
-
} catch {
|
|
373
|
-
// Vite unavailable, fall through to 404
|
|
374
|
-
}
|
|
375
|
-
return c.notFound();
|
|
376
|
-
}
|
|
377
|
-
return devHtmlHandler(c);
|
|
378
|
-
});
|
|
379
|
-
} else {
|
|
380
|
-
// Production mode: Serve static files from bundled output
|
|
381
|
-
const indexHtmlPath = import.meta.dir + '/client/index.html';
|
|
382
|
-
const baseIndexHtml = existsSync(indexHtmlPath)
|
|
383
|
-
? readFileSync(indexHtmlPath, 'utf-8')
|
|
384
|
-
: '';
|
|
385
|
-
|
|
386
|
-
if (!baseIndexHtml) {
|
|
387
|
-
otel.logger.warn('Production HTML not found at %s', indexHtmlPath);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
const prodHtmlHandler = (c: Context) => {
|
|
391
|
-
if (!baseIndexHtml) {
|
|
392
|
-
return c.text('Production build incomplete', 500);
|
|
393
|
-
}
|
|
394
|
-
${analyticsEnabled
|
|
395
|
-
? ` // Inject analytics config and script (session/thread loaded via session.js)
|
|
396
|
-
const html = injectAnalytics(baseIndexHtml, analyticsConfig);
|
|
397
|
-
return c.html(html);`
|
|
398
|
-
: ` return c.html(baseIndexHtml);`}
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
app.get('/', prodHtmlHandler);
|
|
402
|
-
|
|
403
|
-
// Serve static assets from /assets/* (Vite bundled output)
|
|
404
|
-
app.use('/assets/*', serveStatic({ root: import.meta.dir + '/client', mimes: mimeTypes }));
|
|
405
|
-
|
|
406
|
-
// Serve static public assets (favicon.ico, robots.txt, etc.)
|
|
407
|
-
app.use('/*', serveStatic({ root: import.meta.dir + '/client', rewriteRequestPath: (path) => path, mimes: mimeTypes }));
|
|
408
|
-
|
|
409
|
-
// 404 for unmatched API/system routes (IMPORTANT: comes before SPA fallback)
|
|
410
|
-
app.all('/_agentuity/*', (c: Context) => c.notFound());
|
|
411
|
-
app.all('/api/*', (c: Context) => c.notFound());
|
|
412
|
-
if (!(hasWorkbenchConfig && isDevelopment())) {
|
|
413
|
-
app.all('/workbench/*', (c: Context) => c.notFound());
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// SPA fallback with asset protection
|
|
417
|
-
app.get('*', (c: Context) => {
|
|
418
|
-
const path = c.req.path;
|
|
419
|
-
// If path has a file extension, it's likely an asset request - return 404
|
|
420
|
-
if (/\\.[a-zA-Z0-9]+$/.test(path)) {
|
|
421
|
-
return c.notFound();
|
|
422
|
-
}
|
|
423
|
-
return prodHtmlHandler(c);
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
`;
|
|
427
|
-
}
|
|
428
|
-
// Workbench UI routes (development only)
|
|
429
|
-
// The workbench UI is only served in development mode; the API routes are always available
|
|
430
|
-
const workbenchRoute = workbench?.route ?? '/workbench';
|
|
431
|
-
const workbenchRoutes = `
|
|
432
|
-
// Workbench UI is only available in development mode (API routes are always available)
|
|
433
|
-
if (hasWorkbenchConfig && isDevelopment()) {
|
|
434
|
-
const workbenchSrcDir = import.meta.dir + '/workbench-src';
|
|
435
|
-
const workbenchIndexPath = import.meta.dir + '/workbench-src/index.html';
|
|
436
|
-
app.get('${workbenchRoute}', async (c: Context) => {
|
|
437
|
-
const html = await Bun.file(workbenchIndexPath).text();
|
|
438
|
-
// Rewrite script/css paths to use Vite's @fs protocol
|
|
439
|
-
const withVite = html
|
|
440
|
-
.replace('src="./main.tsx"', \`src="/@fs\${workbenchSrcDir}/main.tsx"\`)
|
|
441
|
-
.replace('href="./styles.css"', \`href="/@fs\${workbenchSrcDir}/styles.css"\`);
|
|
442
|
-
return c.html(withVite);
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
`;
|
|
446
|
-
// Server startup (same for dev and prod - Bun.serve with native WebSocket)
|
|
447
|
-
const serverStartup = `
|
|
448
|
-
// Start Bun server
|
|
449
|
-
if (typeof Bun !== 'undefined') {
|
|
450
|
-
// Enable process exit protection now that we're starting the server
|
|
451
|
-
enableProcessExitProtection();
|
|
452
|
-
|
|
453
|
-
const port = parseInt(process.env.PORT || '3500', 10);
|
|
454
|
-
|
|
455
|
-
// Create custom WebSocket handler that supports both regular WebSockets and HMR proxy
|
|
456
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
457
|
-
const hmrHandler = (globalThis as any).__AGENTUITY_VITE_HMR_WEBSOCKET__;
|
|
458
|
-
const customWebsocket = {
|
|
459
|
-
...websocket,
|
|
460
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
461
|
-
open(ws: any) {
|
|
462
|
-
// Check if this is an HMR connection
|
|
463
|
-
if (ws.data?.type === 'vite-hmr' && hmrHandler) {
|
|
464
|
-
hmrHandler.open(ws);
|
|
465
|
-
} else if (websocket.open) {
|
|
466
|
-
websocket.open(ws);
|
|
467
|
-
}
|
|
468
|
-
},
|
|
469
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
470
|
-
message(ws: any, message: string | Buffer) {
|
|
471
|
-
// Check if this is an HMR connection
|
|
472
|
-
if (ws.data?.type === 'vite-hmr' && hmrHandler) {
|
|
473
|
-
hmrHandler.message(ws, message);
|
|
474
|
-
} else if (websocket.message) {
|
|
475
|
-
websocket.message(ws, message);
|
|
476
|
-
}
|
|
477
|
-
},
|
|
478
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
479
|
-
close(ws: any, code?: number, reason?: string) {
|
|
480
|
-
// Check if this is an HMR connection
|
|
481
|
-
if (ws.data?.type === 'vite-hmr' && hmrHandler) {
|
|
482
|
-
hmrHandler.close(ws);
|
|
483
|
-
} else if (websocket.close) {
|
|
484
|
-
websocket.close(ws, code, reason);
|
|
485
|
-
}
|
|
486
|
-
},
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
const server = Bun.serve({
|
|
490
|
-
fetch: (req, server) => {
|
|
491
|
-
// Get timeout from config on each request (0 = no timeout)
|
|
492
|
-
server.timeout(req, getAppConfig()?.requestTimeout ?? 0);
|
|
493
|
-
return app.fetch(req, server);
|
|
494
|
-
},
|
|
495
|
-
websocket: customWebsocket,
|
|
496
|
-
port,
|
|
497
|
-
hostname: '127.0.0.1',
|
|
498
|
-
development: isDevelopment(),
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
// Make server available globally for health checks
|
|
502
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
503
|
-
(globalThis as any).__AGENTUITY_SERVER__ = server;
|
|
504
|
-
|
|
505
|
-
otel.logger.info(\`Server listening on http://127.0.0.1:\${port}\`);
|
|
506
|
-
if (isDevelopment() && process.env.VITE_PORT) {
|
|
507
|
-
otel.logger.debug(\`Proxying Vite assets from port \${process.env.VITE_PORT}\`);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// Register signal handlers for graceful shutdown (production only)
|
|
511
|
-
// Dev mode has its own handlers in devmode.ts
|
|
512
|
-
if (!isDevelopment()) {
|
|
513
|
-
const handleShutdown = async (signal: string) => {
|
|
514
|
-
otel.logger.info(\`Received \${signal}, initiating graceful shutdown...\`);
|
|
515
|
-
try {
|
|
516
|
-
await runShutdown();
|
|
517
|
-
otel.logger.info('Shutdown complete');
|
|
518
|
-
} catch (err) {
|
|
519
|
-
otel.logger.error(\`Error during shutdown: \${err instanceof Error ? err.message : String(err)}\`);
|
|
520
|
-
}
|
|
521
|
-
process.exit(0);
|
|
522
|
-
};
|
|
523
|
-
|
|
524
|
-
process.once('SIGTERM', () => handleShutdown('SIGTERM'));
|
|
525
|
-
process.once('SIGINT', () => handleShutdown('SIGINT'));
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// FOUND AN ERROR IN THIS FILE?
|
|
530
|
-
// Please file an issue at https://github.com/agentuity/sdk/issues
|
|
531
|
-
// or if you know the fix please submit a PR!
|
|
532
|
-
`;
|
|
533
|
-
const healthRoutes = `
|
|
534
|
-
// Health check routes (production only)
|
|
535
|
-
if (!isDevelopment()) {
|
|
536
|
-
const healthHandler = (c: Context) => {
|
|
537
|
-
return c.text('OK', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
538
|
-
};
|
|
539
|
-
const idleHandler = (c: Context) => {
|
|
540
|
-
// Check if server is idle (no pending requests/connections)
|
|
541
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
542
|
-
const server = (globalThis as any).__AGENTUITY_SERVER__;
|
|
543
|
-
if (!server) return c.text('NO', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
544
|
-
|
|
545
|
-
// Check for pending background tasks
|
|
546
|
-
if (hasWaitUntilPending()) return c.text('NO', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
547
|
-
|
|
548
|
-
if (server.pendingRequests > 1) return c.text('NO', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
549
|
-
if (server.pendingWebSockets > 0) return c.text('NO', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
550
|
-
|
|
551
|
-
return c.text('OK', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
552
|
-
};
|
|
553
|
-
app.get('/_agentuity/health', healthHandler);
|
|
554
|
-
app.get('/_health', healthHandler);
|
|
555
|
-
app.get('/_agentuity/idle', idleHandler);
|
|
556
|
-
app.get('/_idle', idleHandler);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
// Dev readiness check - verifies Vite asset server is ready to serve frontend
|
|
560
|
-
if (isDevelopment()) {
|
|
561
|
-
app.get('/_agentuity/ready', async (c: Context) => {
|
|
562
|
-
const vitePort = process.env.VITE_PORT;
|
|
563
|
-
if (!vitePort) {
|
|
564
|
-
// No Vite port means we're not using Vite proxy
|
|
565
|
-
return c.text('OK', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
try {
|
|
569
|
-
// Probe Vite to check if it can serve the main entry point
|
|
570
|
-
// Use @vite/client as a lightweight check - it's always available
|
|
571
|
-
const viteUrl = \`http://127.0.0.1:\${vitePort}/@vite/client\`;
|
|
572
|
-
const res = await fetch(viteUrl, {
|
|
573
|
-
signal: AbortSignal.timeout(5000),
|
|
574
|
-
method: 'HEAD'
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
if (res.ok) {
|
|
578
|
-
return c.text('OK', 200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
579
|
-
}
|
|
580
|
-
return c.text('VITE_NOT_READY', 503, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
581
|
-
} catch (err) {
|
|
582
|
-
otel.logger.debug('Vite readiness check failed: %s', err instanceof Error ? err.message : String(err));
|
|
583
|
-
return c.text('VITE_NOT_READY', 503, { 'Content-Type': 'text/plain; charset=utf-8' });
|
|
584
|
-
}
|
|
585
|
-
});
|
|
586
|
-
}
|
|
587
|
-
`;
|
|
588
|
-
const devPatchesStep = noBundle
|
|
589
|
-
? `
|
|
590
|
-
// Step 0.1: Apply runtime dev patches (--experimental-no-bundle mode)
|
|
591
|
-
// Replaces build-time Bun.build patches for LLM gateway routing, AI SDK telemetry, and OTel spans
|
|
592
|
-
if (isDevelopment()) {
|
|
593
|
-
await applyDevPatches();
|
|
594
|
-
}
|
|
595
|
-
`
|
|
596
|
-
: '';
|
|
597
|
-
const code = `// @generated
|
|
598
|
-
// Auto-generated by Agentuity
|
|
599
|
-
// DO NOT EDIT - This file is regenerated on every build
|
|
600
|
-
// Supports both development and production modes via runtime detection
|
|
601
|
-
${imports.join('\n')}
|
|
602
|
-
|
|
603
|
-
${modeDetection}
|
|
604
|
-
|
|
605
|
-
// Step 0: Bootstrap runtime environment (load profile-specific .env files)
|
|
606
|
-
// Only in development - production env vars are injected by platform
|
|
607
|
-
// This must happen BEFORE any imports that depend on environment variables
|
|
608
|
-
if (isDevelopment()) {
|
|
609
|
-
// Pass project directory (two levels up from src/generated/) so .env files are loaded correctly
|
|
610
|
-
await bootstrapRuntimeEnv({ projectDir: import.meta.dir + '/../..' });
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
${devPatchesStep}
|
|
614
|
-
|
|
615
|
-
// Step 0.25: load our runtime metadata and cache it
|
|
616
|
-
loadBuildMetadata();
|
|
617
|
-
|
|
618
|
-
// Step 0.5: Patch Bun's S3 client for Agentuity storage endpoints
|
|
619
|
-
// Agentuity storage uses virtual-hosted-style URLs (*.storage.dev)
|
|
620
|
-
// This patches s3.file() to automatically set virtualHostedStyle: true
|
|
621
|
-
patchBunS3ForStorageDev();
|
|
622
|
-
|
|
623
|
-
// Step 1: Initialize telemetry and services
|
|
624
|
-
const serverUrl = \`http://127.0.0.1:\${process.env.PORT || '3500'}\`;
|
|
625
|
-
const otel = register({ processors: getSpanProcessors(), logLevel: (process.env.AGENTUITY_LOG_LEVEL || 'info') as LogLevel });
|
|
626
|
-
|
|
627
|
-
// Step 2: Create router and set as global
|
|
628
|
-
const app = createRouter();
|
|
629
|
-
setGlobalRouter(app);
|
|
630
|
-
|
|
631
|
-
// Step 3: Apply middleware in correct order (BEFORE mounting routes)
|
|
632
|
-
// Compression runs first (outermost) so it can compress the final response
|
|
633
|
-
app.use('*', createCompressionMiddleware());
|
|
634
|
-
|
|
635
|
-
app.use('*', createBaseMiddleware({
|
|
636
|
-
logger: otel.logger,
|
|
637
|
-
tracer: otel.tracer,
|
|
638
|
-
meter: otel.meter,
|
|
639
|
-
}));
|
|
640
|
-
|
|
641
|
-
// Workbench routes always get OTel middleware for session tracking
|
|
642
|
-
app.use('/_agentuity/workbench/*', createOtelMiddleware());
|
|
643
|
-
|
|
644
|
-
// Note: /api/* middleware (CORS, OTel, agent context) is applied in Step 6
|
|
645
|
-
// after app.ts import, so user-provided routers can specify custom prefixes.
|
|
646
|
-
|
|
647
|
-
// Step 4: Import user's app.ts (runs createApp, gets state/config)
|
|
648
|
-
await import('../../app.js');
|
|
649
|
-
|
|
650
|
-
// Step 4.5: Import agent registry to ensure all agents are registered
|
|
651
|
-
// This is needed for workbench metadata to return JSON schemas
|
|
652
|
-
await import('./registry.js');
|
|
653
|
-
|
|
654
|
-
// Step 5: Initialize providers
|
|
655
|
-
const appState = getAppState();
|
|
656
|
-
const appConfig = getAppConfig();
|
|
657
|
-
|
|
658
|
-
createServices(otel.logger, appConfig, serverUrl);
|
|
659
|
-
|
|
660
|
-
// Make logger and tracer globally available for user's app.ts
|
|
661
|
-
setGlobalLogger(otel.logger);
|
|
662
|
-
setGlobalTracer(otel.tracer);
|
|
663
|
-
|
|
664
|
-
const threadProvider = getThreadProvider();
|
|
665
|
-
const sessionProvider = getSessionProvider();
|
|
666
|
-
|
|
667
|
-
await threadProvider.initialize(appState);
|
|
668
|
-
await sessionProvider.initialize(appState);
|
|
669
|
-
|
|
670
|
-
// Step 6: Mount routes (AFTER middleware is applied)
|
|
671
|
-
|
|
672
|
-
${healthRoutes}
|
|
673
|
-
|
|
674
|
-
${analyticsEnabled
|
|
675
|
-
? `// Register analytics routes
|
|
676
|
-
registerAnalyticsRoutes(app);`
|
|
677
|
-
: ''}
|
|
678
|
-
|
|
679
|
-
${assetProxyRoutes}
|
|
680
|
-
${apiMount}
|
|
681
|
-
${workbenchApiMount}
|
|
682
|
-
${workbenchRoutes}
|
|
683
|
-
${webRoutes}
|
|
684
|
-
|
|
685
|
-
// Step 7: Run agent setup to signal completion
|
|
686
|
-
await runAgentSetups(appState);
|
|
687
|
-
|
|
688
|
-
${serverStartup}
|
|
689
|
-
`;
|
|
690
|
-
// Collapse 2+ consecutive empty lines into 1 empty line (3+ \n becomes 2 \n)
|
|
691
|
-
const cleanedCode = code.replace(/\n{3,}/g, '\n\n');
|
|
692
|
-
await Bun.write(entryPath, cleanedCode);
|
|
693
|
-
logger.trace(`Generated unified entry file at %s (mode: ${mode})`, entryPath);
|
|
694
|
-
}
|
|
695
|
-
//# sourceMappingURL=entry-generator.js.map
|