@agentuity/runtime 1.0.48 → 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/_globals.d.ts +58 -0
- package/dist/_globals.d.ts.map +1 -0
- package/dist/_globals.js +71 -0
- package/dist/_globals.js.map +1 -0
- package/dist/_metadata.d.ts.map +1 -1
- package/dist/_metadata.js +14 -0
- package/dist/_metadata.js.map +1 -1
- package/dist/_process-protection.d.ts +2 -0
- package/dist/_process-protection.d.ts.map +1 -1
- package/dist/_process-protection.js +14 -23
- package/dist/_process-protection.js.map +1 -1
- package/dist/_server.d.ts +4 -0
- package/dist/_server.d.ts.map +1 -1
- package/dist/_server.js +4 -0
- package/dist/_server.js.map +1 -1
- package/dist/_services.d.ts +1 -1
- package/dist/_services.d.ts.map +1 -1
- package/dist/_services.js +5 -1
- package/dist/_services.js.map +1 -1
- package/dist/_standalone.d.ts.map +1 -1
- package/dist/_standalone.js +3 -9
- package/dist/_standalone.js.map +1 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +1 -0
- package/dist/agent.js.map +1 -1
- package/dist/app.d.ts +149 -71
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +121 -156
- package/dist/app.js.map +1 -1
- package/dist/bootstrap.d.ts +44 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +256 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/dev-patches/aisdk.d.ts.map +1 -1
- package/dist/dev-patches/aisdk.js +6 -8
- package/dist/dev-patches/aisdk.js.map +1 -1
- package/dist/dev-patches/gateway.d.ts.map +1 -1
- package/dist/dev-patches/gateway.js +7 -8
- package/dist/dev-patches/gateway.js.map +1 -1
- package/dist/handlers/_route-meta.d.ts +20 -0
- package/dist/handlers/_route-meta.d.ts.map +1 -0
- package/dist/handlers/_route-meta.js +25 -0
- package/dist/handlers/_route-meta.js.map +1 -0
- package/dist/handlers/cron.d.ts.map +1 -1
- package/dist/handlers/cron.js +3 -1
- package/dist/handlers/cron.js.map +1 -1
- package/dist/handlers/sse.d.ts +3 -3
- package/dist/handlers/sse.d.ts.map +1 -1
- package/dist/handlers/sse.js +4 -16
- package/dist/handlers/sse.js.map +1 -1
- package/dist/handlers/stream.d.ts.map +1 -1
- package/dist/handlers/stream.js +4 -12
- package/dist/handlers/stream.js.map +1 -1
- package/dist/handlers/websocket.d.ts +3 -1
- package/dist/handlers/websocket.d.ts.map +1 -1
- package/dist/handlers/websocket.js +6 -37
- package/dist/handlers/websocket.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware.d.ts +1 -8
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +29 -71
- package/dist/middleware.js.map +1 -1
- package/dist/otel/logger.d.ts.map +1 -1
- package/dist/otel/logger.js +4 -7
- package/dist/otel/logger.js.map +1 -1
- package/dist/otel/otel.d.ts +4 -1
- package/dist/otel/otel.d.ts.map +1 -1
- package/dist/otel/otel.js +13 -2
- package/dist/otel/otel.js.map +1 -1
- package/dist/router.d.ts +10 -62
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +9 -146
- package/dist/router.js.map +1 -1
- package/dist/workbench.d.ts +1 -1
- package/dist/workbench.d.ts.map +1 -1
- package/dist/workbench.js +120 -12
- package/dist/workbench.js.map +1 -1
- package/package.json +7 -7
- package/src/_globals.ts +92 -0
- package/src/_metadata.ts +14 -0
- package/src/_process-protection.ts +17 -28
- package/src/_server.ts +4 -0
- package/src/_services.ts +6 -2
- package/src/_standalone.ts +4 -9
- package/src/agent.ts +1 -0
- package/src/app.ts +294 -195
- package/src/bootstrap.ts +316 -0
- package/src/dev-patches/aisdk.ts +8 -11
- package/src/dev-patches/gateway.ts +9 -11
- package/src/globals.d.ts +28 -0
- package/src/handlers/_route-meta.ts +31 -0
- package/src/handlers/cron.ts +4 -1
- package/src/handlers/sse.ts +8 -19
- package/src/handlers/stream.ts +5 -12
- package/src/handlers/websocket.ts +11 -37
- package/src/index.ts +2 -3
- package/src/middleware.ts +40 -99
- package/src/otel/logger.ts +5 -8
- package/src/otel/otel.ts +14 -2
- package/src/router.ts +12 -216
- package/src/workbench.ts +135 -12
package/src/app.ts
CHANGED
|
@@ -124,7 +124,47 @@ export interface CompressionConfig {
|
|
|
124
124
|
honoOptions?: HonoCompressOptions;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
/**
|
|
128
|
+
* Web analytics configuration options.
|
|
129
|
+
*/
|
|
130
|
+
export interface AnalyticsOptions {
|
|
131
|
+
/** Enable/disable analytics @default true */
|
|
132
|
+
enabled?: boolean;
|
|
133
|
+
/** Require explicit user consent before tracking @default false */
|
|
134
|
+
requireConsent?: boolean;
|
|
135
|
+
/** Track click events on elements with data-analytics attribute @default true */
|
|
136
|
+
trackClicks?: boolean;
|
|
137
|
+
/** Track scroll depth @default true */
|
|
138
|
+
trackScroll?: boolean;
|
|
139
|
+
/** Track outbound link clicks @default true */
|
|
140
|
+
trackOutboundLinks?: boolean;
|
|
141
|
+
/** Track form submissions @default false */
|
|
142
|
+
trackForms?: boolean;
|
|
143
|
+
/** Track Core Web Vitals (LCP, FID, CLS) @default true */
|
|
144
|
+
trackWebVitals?: boolean;
|
|
145
|
+
/** Track JavaScript errors @default true */
|
|
146
|
+
trackErrors?: boolean;
|
|
147
|
+
/** Track SPA navigation changes @default true */
|
|
148
|
+
trackSPANavigation?: boolean;
|
|
149
|
+
/** Sampling rate (0-1) @default 1 */
|
|
150
|
+
sampleRate?: number;
|
|
151
|
+
/** URL patterns to exclude from tracking */
|
|
152
|
+
excludePatterns?: string[];
|
|
153
|
+
/** Global properties attached to every event */
|
|
154
|
+
globalProperties?: Record<string, unknown>;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Workbench UI configuration options.
|
|
159
|
+
*/
|
|
160
|
+
export interface WorkbenchOptions {
|
|
161
|
+
/** Route path for the workbench UI @default '/workbench' */
|
|
162
|
+
route?: string;
|
|
163
|
+
/** Custom headers to include in workbench responses */
|
|
164
|
+
headers?: Record<string, string>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface AppConfig {
|
|
128
168
|
/**
|
|
129
169
|
* Configure CORS (Cross-Origin Resource Sharing) settings.
|
|
130
170
|
*
|
|
@@ -211,21 +251,62 @@ export interface AppConfig<TAppState = Record<string, never>> {
|
|
|
211
251
|
email?: EmailService;
|
|
212
252
|
};
|
|
213
253
|
/**
|
|
214
|
-
* Optional
|
|
215
|
-
*
|
|
254
|
+
* Optional request timeout in seconds. If not provided, will default
|
|
255
|
+
* to zero which will cause the request to wait indefinitely.
|
|
216
256
|
*/
|
|
217
|
-
|
|
257
|
+
requestTimeout?: number;
|
|
258
|
+
|
|
218
259
|
/**
|
|
219
|
-
*
|
|
220
|
-
*
|
|
260
|
+
* Configure web analytics for frontend tracking.
|
|
261
|
+
*
|
|
262
|
+
* Set to `true` to enable with defaults, `false` to disable, or provide
|
|
263
|
+
* a configuration object to customize tracking behavior.
|
|
264
|
+
*
|
|
265
|
+
* @default true
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```typescript
|
|
269
|
+
* // Enable with defaults
|
|
270
|
+
* const app = await createApp({ analytics: true });
|
|
271
|
+
*
|
|
272
|
+
* // Disable analytics
|
|
273
|
+
* const app = await createApp({ analytics: false });
|
|
274
|
+
*
|
|
275
|
+
* // Custom configuration
|
|
276
|
+
* const app = await createApp({
|
|
277
|
+
* analytics: {
|
|
278
|
+
* trackClicks: false,
|
|
279
|
+
* sampleRate: 0.5,
|
|
280
|
+
* }
|
|
281
|
+
* });
|
|
282
|
+
* ```
|
|
221
283
|
*/
|
|
222
|
-
|
|
284
|
+
analytics?: boolean | AnalyticsOptions;
|
|
223
285
|
|
|
224
286
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
287
|
+
* Configure the workbench UI for agent testing.
|
|
288
|
+
*
|
|
289
|
+
* Set to `true` to enable at `/workbench`, a string to set a custom route,
|
|
290
|
+
* or an object for full configuration. Only active in development mode.
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* // Enable at default route (/workbench)
|
|
295
|
+
* const app = await createApp({ workbench: true });
|
|
296
|
+
*
|
|
297
|
+
* // Custom route
|
|
298
|
+
* const app = await createApp({ workbench: '/debug' });
|
|
299
|
+
*
|
|
300
|
+
* // Full configuration
|
|
301
|
+
* const app = await createApp({
|
|
302
|
+
* workbench: {
|
|
303
|
+
* route: '/debug',
|
|
304
|
+
* headers: { 'X-Custom': 'value' },
|
|
305
|
+
* }
|
|
306
|
+
* });
|
|
307
|
+
* ```
|
|
227
308
|
*/
|
|
228
|
-
|
|
309
|
+
workbench?: boolean | string | WorkbenchOptions;
|
|
229
310
|
|
|
230
311
|
/**
|
|
231
312
|
* **Experimental** — Optional user-provided router(s) to use instead of file-based routing.
|
|
@@ -273,6 +354,31 @@ export interface AppConfig<TAppState = Record<string, never>> {
|
|
|
273
354
|
*/
|
|
274
355
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
275
356
|
router?: import('hono').Hono<any, any, any> | RouteMount | RouteMount[];
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Agents to register with this application.
|
|
360
|
+
*
|
|
361
|
+
* Each agent is a value returned by `createAgent()`. Importing the agent
|
|
362
|
+
* module triggers self-registration; listing them here ensures they are
|
|
363
|
+
* included in the build and available for workbench metadata, setup/shutdown
|
|
364
|
+
* lifecycle, and agent-to-agent calls via `ctx.invoke()`.
|
|
365
|
+
*
|
|
366
|
+
* Type safety for agent calls comes from direct imports — use
|
|
367
|
+
* `ctx.invoke(() => myAgent.run(input))` for fully typed invocations.
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
* ```typescript
|
|
371
|
+
* import greeting from './agent/greeting/agent';
|
|
372
|
+
* import session from './agent/session/agent';
|
|
373
|
+
*
|
|
374
|
+
* export default await createApp({
|
|
375
|
+
* agents: [greeting, session],
|
|
376
|
+
* router,
|
|
377
|
+
* });
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
380
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
381
|
+
agents?: import('./agent').AgentRunner<any, any, any>[];
|
|
276
382
|
}
|
|
277
383
|
|
|
278
384
|
/**
|
|
@@ -337,12 +443,7 @@ export function getApp(): null {
|
|
|
337
443
|
|
|
338
444
|
// Re-export event functions from _events
|
|
339
445
|
export { fireEvent } from './_events';
|
|
340
|
-
|
|
341
|
-
addEventListener as globalAddEventListener,
|
|
342
|
-
removeEventListener as globalRemoveEventListener,
|
|
343
|
-
} from './_events';
|
|
344
|
-
import type { AppEventMap } from './_events';
|
|
345
|
-
import { getLogger, getRouter } from './_server';
|
|
446
|
+
|
|
346
447
|
import type { Hono } from 'hono';
|
|
347
448
|
|
|
348
449
|
// ============================================================================
|
|
@@ -359,180 +460,213 @@ export interface Server {
|
|
|
359
460
|
url: string;
|
|
360
461
|
}
|
|
361
462
|
|
|
362
|
-
export interface AppResult
|
|
463
|
+
export interface AppResult {
|
|
363
464
|
/**
|
|
364
|
-
*
|
|
465
|
+
* App configuration
|
|
365
466
|
*/
|
|
366
|
-
|
|
467
|
+
config?: AppConfig;
|
|
367
468
|
/**
|
|
368
|
-
*
|
|
469
|
+
* The Hono router instance
|
|
369
470
|
*/
|
|
370
|
-
|
|
471
|
+
router: import('hono').Hono<Env>;
|
|
371
472
|
/**
|
|
372
|
-
*
|
|
473
|
+
* Server information
|
|
373
474
|
*/
|
|
374
|
-
|
|
475
|
+
server: Server;
|
|
375
476
|
/**
|
|
376
|
-
*
|
|
477
|
+
* Logger instance
|
|
377
478
|
*/
|
|
378
|
-
|
|
479
|
+
logger: Logger;
|
|
379
480
|
/**
|
|
380
|
-
*
|
|
481
|
+
* Fetch handler for the application.
|
|
482
|
+
* Bun --hot uses this on the default export to hot-swap the running server's
|
|
483
|
+
* request handler without restarting the process.
|
|
381
484
|
*/
|
|
382
|
-
|
|
485
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
486
|
+
fetch: (req: Request, ...args: any[]) => Response | Promise<Response>;
|
|
383
487
|
/**
|
|
384
|
-
*
|
|
488
|
+
* Port the server listens on.
|
|
489
|
+
* Used by Bun --hot alongside `fetch` to configure the server.
|
|
385
490
|
*/
|
|
386
|
-
|
|
491
|
+
port: number;
|
|
387
492
|
/**
|
|
388
|
-
*
|
|
493
|
+
* Hostname the server binds to.
|
|
389
494
|
*/
|
|
390
|
-
|
|
391
|
-
eventName: K,
|
|
392
|
-
callback: (eventName: K, ...args: AppEventMap<TAppState>[K]) => void | Promise<void>
|
|
393
|
-
): void;
|
|
495
|
+
hostname: string;
|
|
394
496
|
/**
|
|
395
|
-
*
|
|
497
|
+
* WebSocket handler for Bun.serve().
|
|
498
|
+
* Required by Bun --hot to enable WebSocket upgrade support.
|
|
396
499
|
*/
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
callback: (eventName: K, ...args: AppEventMap<TAppState>[K]) => void | Promise<void>
|
|
400
|
-
): void;
|
|
500
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
501
|
+
websocket?: any;
|
|
401
502
|
}
|
|
402
503
|
|
|
403
504
|
/**
|
|
404
|
-
* Create an Agentuity application
|
|
405
|
-
*
|
|
406
|
-
* In Vite-native architecture:
|
|
407
|
-
* - This only handles setup/shutdown lifecycle
|
|
408
|
-
* - Router creation and middleware are handled by the generated entry file
|
|
409
|
-
* - Server is managed by Vite (dev) or Bun.serve (prod)
|
|
505
|
+
* Create and start an Agentuity application.
|
|
410
506
|
*
|
|
411
|
-
*
|
|
507
|
+
* This is the single entry point for the entire server lifecycle:
|
|
508
|
+
* OTel, middleware, route mounting, services, and Bun.serve().
|
|
412
509
|
*
|
|
413
510
|
* @example
|
|
414
511
|
* ```typescript
|
|
415
|
-
* // app.ts
|
|
416
512
|
* import { createApp } from '@agentuity/runtime';
|
|
513
|
+
* import router from './src/api/router';
|
|
514
|
+
* import agents from './src/agent';
|
|
417
515
|
*
|
|
418
|
-
*
|
|
419
|
-
*
|
|
420
|
-
*
|
|
421
|
-
* return { db };
|
|
422
|
-
* },
|
|
423
|
-
* shutdown: async (state) => {
|
|
424
|
-
* await state.db.close();
|
|
425
|
-
* }
|
|
516
|
+
* export default await createApp({
|
|
517
|
+
* router: { path: '/api', router },
|
|
518
|
+
* agents,
|
|
426
519
|
* });
|
|
427
|
-
*
|
|
428
|
-
* // Access state in agents via ctx.app.db
|
|
429
520
|
* ```
|
|
430
521
|
*/
|
|
431
|
-
export async function createApp
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
522
|
+
export async function createApp(config?: AppConfig): Promise<AppResult> {
|
|
523
|
+
// --- Imports (lazy to avoid circular deps) ---
|
|
524
|
+
const { bootstrapRuntimeEnv } = await import('@agentuity/server');
|
|
525
|
+
const { register } = await import('./otel/config');
|
|
526
|
+
const { setGlobalLogger, setGlobalTracer, setGlobalRouter, getSpanProcessors } = await import(
|
|
527
|
+
'./_server'
|
|
528
|
+
);
|
|
529
|
+
const { createServices, getThreadProvider, getSessionProvider } = await import('./_services');
|
|
530
|
+
const {
|
|
531
|
+
createBaseMiddleware,
|
|
532
|
+
createCorsMiddleware,
|
|
533
|
+
createOtelMiddleware,
|
|
534
|
+
createCompressionMiddleware,
|
|
535
|
+
} = await import('./middleware');
|
|
536
|
+
const { runAgentSetups, createAgentMiddleware } = await import('./agent');
|
|
537
|
+
const { loadBuildMetadata } = await import('./_metadata');
|
|
538
|
+
const { patchBunS3ForStorageDev } = await import('./bun-s3-patch');
|
|
539
|
+
const { createWorkbenchRouter } = await import('./workbench');
|
|
540
|
+
const {
|
|
541
|
+
isDevelopment,
|
|
542
|
+
resolveAnalyticsConfig,
|
|
543
|
+
resolveWorkbenchConfig,
|
|
544
|
+
registerHealthRoutes,
|
|
545
|
+
registerAnalyticsRoutes,
|
|
546
|
+
registerWebRoutes,
|
|
547
|
+
registerWorkbenchUI,
|
|
548
|
+
startServer,
|
|
549
|
+
} = await import('./bootstrap');
|
|
550
|
+
const { websocket } = await import('hono/bun');
|
|
551
|
+
|
|
552
|
+
// --- Step 0: Environment ---
|
|
553
|
+
if (isDevelopment()) {
|
|
554
|
+
bootstrapRuntimeEnv();
|
|
555
|
+
}
|
|
556
|
+
if (isDevelopment() && process.env.AGENTUITY_NO_BUNDLE === 'true') {
|
|
557
|
+
const { applyDevPatches } = await import('./dev-patches');
|
|
558
|
+
await applyDevPatches();
|
|
559
|
+
}
|
|
560
|
+
loadBuildMetadata();
|
|
561
|
+
patchBunS3ForStorageDev();
|
|
562
|
+
|
|
563
|
+
// --- Step 1: Telemetry ---
|
|
564
|
+
const otel = register({
|
|
565
|
+
processors: getSpanProcessors(),
|
|
566
|
+
logLevel: (process.env.AGENTUITY_LOG_LEVEL || 'info') as import('@agentuity/core').LogLevel,
|
|
567
|
+
});
|
|
568
|
+
setGlobalLogger(otel.logger);
|
|
569
|
+
setGlobalTracer(otel.tracer);
|
|
570
|
+
|
|
571
|
+
// --- Step 2: Router + middleware ---
|
|
572
|
+
const { createRouter } = await import('./router');
|
|
573
|
+
const app = createRouter();
|
|
574
|
+
setGlobalRouter(app);
|
|
575
|
+
|
|
576
|
+
app.use('*', createCompressionMiddleware(config?.compression));
|
|
577
|
+
app.use(
|
|
578
|
+
'*',
|
|
579
|
+
createBaseMiddleware({
|
|
580
|
+
logger: otel.logger,
|
|
581
|
+
tracer: otel.tracer,
|
|
582
|
+
meter: otel.meter,
|
|
583
|
+
})
|
|
584
|
+
);
|
|
585
|
+
app.use('/_agentuity/workbench/*', createOtelMiddleware());
|
|
586
|
+
|
|
587
|
+
// --- Step 3: Services ---
|
|
588
|
+
const port = process.env.PORT || '3500';
|
|
589
|
+
const serverUrl = `http://127.0.0.1:${port}`;
|
|
590
|
+
createServices(otel.logger, config, serverUrl);
|
|
591
|
+
|
|
592
|
+
const threadProvider = getThreadProvider();
|
|
593
|
+
const sessionProvider = getSessionProvider();
|
|
594
|
+
await threadProvider.initialize({});
|
|
595
|
+
await sessionProvider.initialize({});
|
|
596
|
+
|
|
597
|
+
// --- Step 4: Routes ---
|
|
598
|
+
const analyticsConfig = resolveAnalyticsConfig(config?.analytics);
|
|
599
|
+
const workbenchConfig = resolveWorkbenchConfig(config?.workbench);
|
|
600
|
+
|
|
601
|
+
registerHealthRoutes(app);
|
|
602
|
+
|
|
603
|
+
if (analyticsConfig.enabled) {
|
|
604
|
+
registerAnalyticsRoutes(app, analyticsConfig);
|
|
445
605
|
}
|
|
446
606
|
|
|
447
|
-
//
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
(
|
|
607
|
+
// Mount user routers
|
|
608
|
+
if (config?.router) {
|
|
609
|
+
const mounts = normalizeRouterConfig(config.router);
|
|
610
|
+
for (const mount of mounts) {
|
|
611
|
+
const prefix = mount.path.endsWith('/') ? mount.path + '*' : mount.path + '/*';
|
|
612
|
+
app.use(prefix, createCorsMiddleware(config?.cors));
|
|
613
|
+
app.use(prefix, createOtelMiddleware());
|
|
614
|
+
app.use(prefix, createAgentMiddleware(''));
|
|
615
|
+
app.route(mount.path, mount.router);
|
|
616
|
+
}
|
|
451
617
|
}
|
|
452
618
|
|
|
453
|
-
//
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
const logger: Logger = {
|
|
458
|
-
trace: (...args) => {
|
|
459
|
-
const gl = getLogger();
|
|
460
|
-
if (gl) gl.trace(...args);
|
|
461
|
-
},
|
|
462
|
-
debug: (...args) => {
|
|
463
|
-
const gl = getLogger();
|
|
464
|
-
if (gl) gl.debug(...args);
|
|
465
|
-
},
|
|
466
|
-
info: (...args) => {
|
|
467
|
-
const gl = getLogger();
|
|
468
|
-
if (gl) gl.info(...args);
|
|
469
|
-
else console.log('[INFO]', ...args);
|
|
470
|
-
},
|
|
471
|
-
warn: (...args) => {
|
|
472
|
-
const gl = getLogger();
|
|
473
|
-
if (gl) gl.warn(...args);
|
|
474
|
-
else console.warn('[WARN]', ...args);
|
|
475
|
-
},
|
|
476
|
-
error: (...args) => {
|
|
477
|
-
const gl = getLogger();
|
|
478
|
-
if (gl) gl.error(...args);
|
|
479
|
-
else console.error('[ERROR]', ...args);
|
|
480
|
-
},
|
|
481
|
-
fatal: (...args): never => {
|
|
482
|
-
const gl = getLogger();
|
|
483
|
-
if (gl) return gl.fatal(...args);
|
|
484
|
-
// Fallback: log to console but let the real logger handle exit
|
|
485
|
-
console.error('[FATAL]', ...args);
|
|
486
|
-
throw new Error('Fatal error');
|
|
487
|
-
},
|
|
488
|
-
child: (bindings) => {
|
|
489
|
-
const gl = getLogger();
|
|
490
|
-
return gl ? gl.child(bindings) : logger;
|
|
491
|
-
},
|
|
492
|
-
};
|
|
619
|
+
// Workbench
|
|
620
|
+
const workbenchRouter = createWorkbenchRouter();
|
|
621
|
+
app.route('/', workbenchRouter);
|
|
622
|
+
registerWorkbenchUI(app, workbenchConfig);
|
|
493
623
|
|
|
494
|
-
//
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
};
|
|
624
|
+
// Web (production static serving)
|
|
625
|
+
registerWebRoutes(app, analyticsConfig);
|
|
626
|
+
|
|
627
|
+
// --- Step 5: Agent lifecycle + server ---
|
|
628
|
+
await runAgentSetups({});
|
|
629
|
+
|
|
630
|
+
// In dev mode with --hot, Bun manages the server via the default export's
|
|
631
|
+
// `fetch` property. In production, we start Bun.serve() explicitly.
|
|
632
|
+
if (!isDevelopment()) {
|
|
633
|
+
startServer(app, { requestTimeout: config?.requestTimeout });
|
|
634
|
+
}
|
|
499
635
|
|
|
500
|
-
//
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
'Router is not available. Ensure router is initialized before calling createApp(). This typically happens during bundling or when the entry file has not properly set up the router.'
|
|
506
|
-
);
|
|
636
|
+
// Only log on first startup, not on --hot reloads
|
|
637
|
+
const { serverStarted } = await import('./_globals');
|
|
638
|
+
if (!serverStarted.get()) {
|
|
639
|
+
serverStarted.set(true);
|
|
640
|
+
otel.logger.debug('Server listening on %s', serverUrl);
|
|
507
641
|
}
|
|
508
|
-
const router = globalRouter as Hono<Env<TAppState>>;
|
|
509
642
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
643
|
+
const portNumber = parseInt(port, 10);
|
|
644
|
+
|
|
645
|
+
const result: AppResult = {
|
|
513
646
|
config,
|
|
514
|
-
router
|
|
515
|
-
server,
|
|
516
|
-
logger,
|
|
517
|
-
|
|
518
|
-
|
|
647
|
+
router: app as Hono<Env>,
|
|
648
|
+
server: { url: serverUrl },
|
|
649
|
+
logger: otel.logger,
|
|
650
|
+
// Bun --hot picks up `fetch` and `port` on the default export to
|
|
651
|
+
// hot-swap the running server's request handler without restarting.
|
|
652
|
+
fetch: app.fetch,
|
|
653
|
+
port: portNumber,
|
|
654
|
+
hostname: '127.0.0.1',
|
|
655
|
+
websocket,
|
|
519
656
|
};
|
|
520
|
-
}
|
|
521
657
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
658
|
+
// In production, startServer() already called Bun.serve(). If we leave
|
|
659
|
+
// `fetch` + `port` on the default export, Bun v1.2+ auto-serves from it
|
|
660
|
+
// too — causing EADDRINUSE. Strip those properties so only the explicit
|
|
661
|
+
// Bun.serve() is active.
|
|
662
|
+
if (!isDevelopment()) {
|
|
663
|
+
delete (result as unknown as Record<string, unknown>).fetch;
|
|
664
|
+
delete (result as unknown as Record<string, unknown>).port;
|
|
665
|
+
delete (result as unknown as Record<string, unknown>).hostname;
|
|
666
|
+
delete (result as unknown as Record<string, unknown>).websocket;
|
|
667
|
+
}
|
|
529
668
|
|
|
530
|
-
|
|
531
|
-
* Get the global app config
|
|
532
|
-
* Used by generated entry file for middleware setup
|
|
533
|
-
*/
|
|
534
|
-
export function getAppConfig<TAppState = any>(): AppConfig<TAppState> | undefined {
|
|
535
|
-
return (globalThis as any).__AGENTUITY_APP_CONFIG__;
|
|
669
|
+
return result;
|
|
536
670
|
}
|
|
537
671
|
|
|
538
672
|
/**
|
|
@@ -542,7 +676,7 @@ export function getAppConfig<TAppState = any>(): AppConfig<TAppState> | undefine
|
|
|
542
676
|
* - [{ path, router }, ...] → as-is
|
|
543
677
|
* @internal
|
|
544
678
|
*/
|
|
545
|
-
function normalizeRouterConfig(
|
|
679
|
+
export function normalizeRouterConfig(
|
|
546
680
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
547
681
|
router: import('hono').Hono<any, any, any> | RouteMount | RouteMount[]
|
|
548
682
|
): RouteMount[] {
|
|
@@ -556,33 +690,6 @@ function normalizeRouterConfig(
|
|
|
556
690
|
return [{ path: '/api', router: router as import('hono').Hono<any, any, any> }];
|
|
557
691
|
}
|
|
558
692
|
|
|
559
|
-
/**
|
|
560
|
-
* Get the user-provided router mounts from createApp({ router }).
|
|
561
|
-
* Returns undefined if no user router was provided (file-based routing).
|
|
562
|
-
* Used by generated entry file to skip file-based route discovery.
|
|
563
|
-
* @internal
|
|
564
|
-
*/
|
|
565
|
-
export function getUserRouter(): RouteMount[] | undefined {
|
|
566
|
-
return (globalThis as any).__AGENTUITY_USER_ROUTER__;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
/**
|
|
570
|
-
* Set the global app config (for testing purposes)
|
|
571
|
-
* @internal
|
|
572
|
-
*/
|
|
573
|
-
export function setAppConfig<TAppState = any>(config: AppConfig<TAppState> | undefined): void {
|
|
574
|
-
if (config === undefined) {
|
|
575
|
-
delete (globalThis as any).__AGENTUITY_APP_CONFIG__;
|
|
576
|
-
} else {
|
|
577
|
-
(globalThis as any).__AGENTUITY_APP_CONFIG__ = config;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
/**
|
|
582
|
-
* Symbol used to store shutdown hooks in globalThis.
|
|
583
|
-
*/
|
|
584
|
-
const SHUTDOWN_HOOKS_KEY = Symbol.for('@agentuity/runtime:shutdown-hooks');
|
|
585
|
-
|
|
586
693
|
/**
|
|
587
694
|
* A shutdown hook function.
|
|
588
695
|
*/
|
|
@@ -592,11 +699,13 @@ export type ShutdownHook = () => Promise<void> | void;
|
|
|
592
699
|
* Gets the global shutdown hooks registry.
|
|
593
700
|
*/
|
|
594
701
|
function getShutdownHooks(): ShutdownHook[] {
|
|
595
|
-
const
|
|
596
|
-
|
|
597
|
-
|
|
702
|
+
const key = Symbol.for('@agentuity/runtime:shutdown-hooks');
|
|
703
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
704
|
+
const g = globalThis as any;
|
|
705
|
+
if (!g[key]) {
|
|
706
|
+
g[key] = [];
|
|
598
707
|
}
|
|
599
|
-
return
|
|
708
|
+
return g[key];
|
|
600
709
|
}
|
|
601
710
|
|
|
602
711
|
/**
|
|
@@ -637,22 +746,12 @@ export function registerShutdownHook(hook: ShutdownHook): () => void {
|
|
|
637
746
|
}
|
|
638
747
|
|
|
639
748
|
/**
|
|
640
|
-
* Run
|
|
641
|
-
* Called
|
|
749
|
+
* Run all registered shutdown hooks.
|
|
750
|
+
* Called during graceful shutdown (SIGTERM/SIGINT).
|
|
642
751
|
*
|
|
643
|
-
*
|
|
644
|
-
* 1. App's shutdown callback (if defined)
|
|
645
|
-
* 2. Registered shutdown hooks (in reverse order - LIFO)
|
|
752
|
+
* Hooks are called in reverse order of registration (LIFO).
|
|
646
753
|
*/
|
|
647
754
|
export async function runShutdown(): Promise<void> {
|
|
648
|
-
// Run app's shutdown callback first
|
|
649
|
-
const shutdown = (globalThis as any).__AGENTUITY_SHUTDOWN__;
|
|
650
|
-
if (shutdown) {
|
|
651
|
-
const state = getAppState();
|
|
652
|
-
await shutdown(state);
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
// Run registered shutdown hooks in reverse order (LIFO)
|
|
656
755
|
const hooks = getShutdownHooks();
|
|
657
756
|
for (let i = hooks.length - 1; i >= 0; i--) {
|
|
658
757
|
const hook = hooks[i];
|