@agentuity/runtime 0.0.42 → 0.0.44
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/AGENTS.md +11 -9
- package/README.md +4 -4
- package/dist/_context.d.ts +12 -4
- package/dist/_context.d.ts.map +1 -1
- package/dist/_server.d.ts +7 -4
- package/dist/_server.d.ts.map +1 -1
- package/dist/_services.d.ts +13 -2
- package/dist/_services.d.ts.map +1 -1
- package/dist/_util.d.ts +1 -1
- package/dist/_util.d.ts.map +1 -1
- package/dist/_waituntil.d.ts +1 -3
- package/dist/_waituntil.d.ts.map +1 -1
- package/dist/agent.d.ts +41 -14
- package/dist/agent.d.ts.map +1 -1
- package/dist/app.d.ts +90 -8
- package/dist/app.d.ts.map +1 -1
- package/dist/eval.d.ts +79 -0
- package/dist/eval.d.ts.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/io/email.d.ts +77 -0
- package/dist/io/email.d.ts.map +1 -0
- package/dist/logger/console.d.ts +21 -1
- package/dist/logger/console.d.ts.map +1 -1
- package/dist/logger/index.d.ts +0 -1
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/user.d.ts +2 -2
- package/dist/logger/user.d.ts.map +1 -1
- package/dist/otel/config.d.ts +3 -1
- package/dist/otel/config.d.ts.map +1 -1
- package/dist/otel/console.d.ts +2 -1
- package/dist/otel/console.d.ts.map +1 -1
- package/dist/otel/exporters/index.d.ts +4 -0
- package/dist/otel/exporters/index.d.ts.map +1 -0
- package/dist/otel/exporters/jsonl-log-exporter.d.ts +36 -0
- package/dist/otel/exporters/jsonl-log-exporter.d.ts.map +1 -0
- package/dist/otel/exporters/jsonl-metric-exporter.d.ts +40 -0
- package/dist/otel/exporters/jsonl-metric-exporter.d.ts.map +1 -0
- package/dist/otel/exporters/jsonl-trace-exporter.d.ts +36 -0
- package/dist/otel/exporters/jsonl-trace-exporter.d.ts.map +1 -0
- package/dist/otel/http.d.ts.map +1 -1
- package/dist/otel/logger.d.ts +15 -11
- package/dist/otel/logger.d.ts.map +1 -1
- package/dist/otel/otel.d.ts +8 -2
- package/dist/otel/otel.d.ts.map +1 -1
- package/dist/router.d.ts +4 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/services/evalrun/composite.d.ts +21 -0
- package/dist/services/evalrun/composite.d.ts.map +1 -0
- package/dist/services/evalrun/http.d.ts +24 -0
- package/dist/services/evalrun/http.d.ts.map +1 -0
- package/dist/services/evalrun/index.d.ts +5 -0
- package/dist/services/evalrun/index.d.ts.map +1 -0
- package/dist/services/evalrun/json.d.ts +21 -0
- package/dist/services/evalrun/json.d.ts.map +1 -0
- package/dist/services/evalrun/local.d.ts +19 -0
- package/dist/services/evalrun/local.d.ts.map +1 -0
- package/dist/services/local/_db.d.ts +4 -0
- package/dist/services/local/_db.d.ts.map +1 -0
- package/dist/services/local/_router.d.ts +3 -0
- package/dist/services/local/_router.d.ts.map +1 -0
- package/dist/services/local/_util.d.ts +18 -0
- package/dist/services/local/_util.d.ts.map +1 -0
- package/dist/services/local/index.d.ts +8 -0
- package/dist/services/local/index.d.ts.map +1 -0
- package/dist/services/local/keyvalue.d.ts +10 -0
- package/dist/services/local/keyvalue.d.ts.map +1 -0
- package/dist/services/local/objectstore.d.ts +11 -0
- package/dist/services/local/objectstore.d.ts.map +1 -0
- package/dist/services/local/stream.d.ts +10 -0
- package/dist/services/local/stream.d.ts.map +1 -0
- package/dist/services/local/vector.d.ts +13 -0
- package/dist/services/local/vector.d.ts.map +1 -0
- package/dist/services/session/composite.d.ts +21 -0
- package/dist/services/session/composite.d.ts.map +1 -0
- package/dist/services/session/http.d.ts +23 -0
- package/dist/services/session/http.d.ts.map +1 -0
- package/dist/services/session/index.d.ts +5 -0
- package/dist/services/session/index.d.ts.map +1 -0
- package/dist/services/session/json.d.ts +22 -0
- package/dist/services/session/json.d.ts.map +1 -0
- package/dist/services/session/local.d.ts +19 -0
- package/dist/services/session/local.d.ts.map +1 -0
- package/dist/session.d.ts +70 -0
- package/dist/session.d.ts.map +1 -0
- package/package.json +10 -6
- package/src/_config.ts +1 -1
- package/src/_context.ts +19 -16
- package/src/_server.ts +284 -42
- package/src/_services.ts +147 -34
- package/src/_util.ts +2 -3
- package/src/_waituntil.ts +5 -153
- package/src/agent.ts +667 -65
- package/src/app.ts +159 -13
- package/src/eval.ts +95 -0
- package/src/index.ts +6 -1
- package/src/io/email.ts +173 -0
- package/src/logger/console.ts +222 -15
- package/src/logger/index.ts +0 -1
- package/src/logger/user.ts +8 -4
- package/src/otel/config.ts +7 -44
- package/src/otel/console.ts +9 -4
- package/src/otel/exporters/README.md +217 -0
- package/src/otel/exporters/index.ts +3 -0
- package/src/otel/exporters/jsonl-log-exporter.ts +113 -0
- package/src/otel/exporters/jsonl-metric-exporter.ts +120 -0
- package/src/otel/exporters/jsonl-trace-exporter.ts +121 -0
- package/src/otel/http.ts +3 -1
- package/src/otel/logger.ts +106 -41
- package/src/otel/otel.ts +43 -22
- package/src/router.ts +44 -4
- package/src/services/evalrun/composite.ts +34 -0
- package/src/services/evalrun/http.ts +112 -0
- package/src/services/evalrun/index.ts +4 -0
- package/src/services/evalrun/json.ts +46 -0
- package/src/services/evalrun/local.ts +28 -0
- package/src/services/local/README.md +1576 -0
- package/src/services/local/_db.ts +182 -0
- package/src/services/local/_router.ts +86 -0
- package/src/services/local/_util.ts +49 -0
- package/src/services/local/index.ts +7 -0
- package/src/services/local/keyvalue.ts +118 -0
- package/src/services/local/objectstore.ts +152 -0
- package/src/services/local/stream.ts +296 -0
- package/src/services/local/vector.ts +264 -0
- package/src/services/session/composite.ts +33 -0
- package/src/services/session/http.ts +64 -0
- package/src/services/session/index.ts +4 -0
- package/src/services/session/json.ts +42 -0
- package/src/services/session/local.ts +28 -0
- package/src/session.ts +284 -0
- package/dist/_unauthenticated.d.ts +0 -26
- package/dist/_unauthenticated.d.ts.map +0 -1
- package/src/_unauthenticated.ts +0 -126
package/src/_server.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
1
|
import {
|
|
3
2
|
context,
|
|
4
3
|
SpanKind,
|
|
@@ -7,29 +6,39 @@ import {
|
|
|
7
6
|
type Tracer,
|
|
8
7
|
trace,
|
|
9
8
|
type Attributes,
|
|
9
|
+
propagation,
|
|
10
10
|
} from '@opentelemetry/api';
|
|
11
|
+
import { TraceState } from '@opentelemetry/core';
|
|
11
12
|
import type { Span } from '@opentelemetry/sdk-trace-base';
|
|
12
13
|
import type { SpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
13
|
-
import { ServiceException } from '@agentuity/core';
|
|
14
|
+
import { type LogLevel, ServiceException } from '@agentuity/core';
|
|
14
15
|
import { cors } from 'hono/cors';
|
|
15
16
|
import { createMiddleware } from 'hono/factory';
|
|
16
|
-
import { Hono } from 'hono';
|
|
17
|
+
import { Hono, type Context as HonoContext } from 'hono';
|
|
17
18
|
import { HTTPException } from 'hono/http-exception';
|
|
18
19
|
import type { BunWebSocketData } from 'hono/bun';
|
|
20
|
+
import { matchedRoutes } from 'hono/route';
|
|
19
21
|
import { websocket } from 'hono/bun';
|
|
20
|
-
import
|
|
22
|
+
import { join } from 'node:path';
|
|
23
|
+
import type { AppConfig, Env, PrivateVariables } from './app';
|
|
21
24
|
import { extractTraceContextFromRequest } from './otel/http';
|
|
22
25
|
import { register } from './otel/config';
|
|
23
26
|
import type { Logger } from './logger';
|
|
24
27
|
import { isIdle } from './_idle';
|
|
25
28
|
import * as runtimeConfig from './_config';
|
|
26
29
|
import { inAgentContext, getAgentContext } from './_context';
|
|
27
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
createServices,
|
|
32
|
+
getThreadProvider,
|
|
33
|
+
getSessionProvider,
|
|
34
|
+
getSessionEventProvider,
|
|
35
|
+
} from './_services';
|
|
36
|
+
import { generateId } from './session';
|
|
37
|
+
import WaitUntilHandler from './_waituntil';
|
|
28
38
|
|
|
29
39
|
let globalServerInstance: Bun.Server<BunWebSocketData> | null = null;
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
let globalAppInstance: Hono<any> | null = null;
|
|
41
|
+
let globalRouterInstance: Hono<Env> | null = null;
|
|
33
42
|
|
|
34
43
|
let globalLogger: Logger | null = null;
|
|
35
44
|
let globalTracer: Tracer | null = null;
|
|
@@ -38,8 +47,8 @@ export function getServer() {
|
|
|
38
47
|
return globalServerInstance;
|
|
39
48
|
}
|
|
40
49
|
|
|
41
|
-
export function
|
|
42
|
-
return
|
|
50
|
+
export function getRouter() {
|
|
51
|
+
return globalRouterInstance;
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
export function getLogger() {
|
|
@@ -57,7 +66,7 @@ function isDevelopment(): boolean {
|
|
|
57
66
|
}
|
|
58
67
|
|
|
59
68
|
function getPort(): number {
|
|
60
|
-
return Number.parseInt(process.env.AGENTUITY_PORT ?? process.env.PORT ?? '
|
|
69
|
+
return Number.parseInt(process.env.AGENTUITY_PORT ?? process.env.PORT ?? '3500', 10) || 3500;
|
|
61
70
|
}
|
|
62
71
|
|
|
63
72
|
const spanProcessors: SpanProcessor[] = [];
|
|
@@ -111,33 +120,46 @@ function registerAgentuitySpanProcessor() {
|
|
|
111
120
|
addSpanProcessor(new RegisterAgentSpanProcessor());
|
|
112
121
|
}
|
|
113
122
|
|
|
114
|
-
export
|
|
123
|
+
export function privateContext<E extends Env>(c: HonoContext<E>) {
|
|
124
|
+
return c as unknown as HonoContext<{ Variables: PrivateVariables }>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const createServer = <E extends Env>(router: Hono<E>, config?: AppConfig) => {
|
|
115
128
|
if (globalServerInstance) {
|
|
116
129
|
return globalServerInstance;
|
|
117
130
|
}
|
|
118
131
|
|
|
119
|
-
|
|
132
|
+
const logLevel = process.env.AGENTUITY_LOG_LEVEL || 'info';
|
|
133
|
+
const port = getPort();
|
|
134
|
+
const hostname = '127.0.0.1';
|
|
135
|
+
const serverUrl = `http://${hostname}:${port}`;
|
|
136
|
+
|
|
137
|
+
// this must come before registering any otel stuff
|
|
120
138
|
registerAgentuitySpanProcessor();
|
|
121
139
|
|
|
140
|
+
// Create the telemetry and logger
|
|
141
|
+
const otel = register({ processors: spanProcessors, logLevel: logLevel as LogLevel });
|
|
142
|
+
|
|
143
|
+
// Create services (may return local router)
|
|
144
|
+
const servicesResult = createServices(otel.logger, config, serverUrl);
|
|
145
|
+
|
|
122
146
|
const server = Bun.serve({
|
|
123
|
-
hostname
|
|
147
|
+
hostname,
|
|
124
148
|
development: isDevelopment(),
|
|
125
|
-
fetch:
|
|
149
|
+
fetch: router.fetch,
|
|
126
150
|
idleTimeout: 0,
|
|
127
|
-
port
|
|
151
|
+
port,
|
|
128
152
|
websocket,
|
|
129
153
|
});
|
|
130
154
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
globalAppInstance = app;
|
|
155
|
+
globalRouterInstance = router as unknown as Hono<Env>;
|
|
134
156
|
globalServerInstance = server;
|
|
135
157
|
globalLogger = otel.logger;
|
|
136
158
|
globalTracer = otel.tracer;
|
|
137
159
|
|
|
138
160
|
let isShutdown = false;
|
|
139
161
|
|
|
140
|
-
|
|
162
|
+
router.onError((error, _c) => {
|
|
141
163
|
if (error instanceof HTTPException) {
|
|
142
164
|
otel.logger.error('HTTP Error: %s (%d)', error.cause, error.status);
|
|
143
165
|
return error.getResponse();
|
|
@@ -150,16 +172,35 @@ export const createServer = <E extends Env>(app: Hono<E>, config?: AppConfig) =>
|
|
|
150
172
|
error instanceof ServiceException ||
|
|
151
173
|
('statusCode' in error && typeof error.statusCode === 'number')
|
|
152
174
|
) {
|
|
153
|
-
|
|
175
|
+
const serviceError = error as ServiceException;
|
|
176
|
+
otel.logger.error(
|
|
177
|
+
'Service Exception: %s (%s returned HTTP status code: %d)',
|
|
178
|
+
error.message,
|
|
179
|
+
serviceError.url,
|
|
180
|
+
serviceError.statusCode
|
|
181
|
+
);
|
|
154
182
|
return new Response(error.message, {
|
|
155
|
-
status:
|
|
183
|
+
status: serviceError.statusCode ?? 500,
|
|
156
184
|
});
|
|
157
185
|
}
|
|
158
|
-
otel.logger.error('Unhandled Server Error: %s', error);
|
|
186
|
+
otel.logger.error('Unhandled Server Error: %s', JSON.stringify(error));
|
|
159
187
|
return new Response('Internal Server Error', { status: 500 });
|
|
160
188
|
});
|
|
161
189
|
|
|
162
|
-
|
|
190
|
+
const threadProvider = getThreadProvider();
|
|
191
|
+
const sessionProvider = getSessionProvider();
|
|
192
|
+
|
|
193
|
+
let initPromise: Promise<void> | undefined = new Promise((resolve, reject) => {
|
|
194
|
+
Promise.all([threadProvider.initialize(), sessionProvider.initialize()])
|
|
195
|
+
.then(() => resolve())
|
|
196
|
+
.catch(reject);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
router.use(async (c, next) => {
|
|
200
|
+
if (initPromise) {
|
|
201
|
+
await initPromise;
|
|
202
|
+
initPromise = undefined;
|
|
203
|
+
}
|
|
163
204
|
c.set('logger', otel.logger);
|
|
164
205
|
c.set('tracer', otel.tracer);
|
|
165
206
|
c.set('meter', otel.meter);
|
|
@@ -169,7 +210,9 @@ export const createServer = <E extends Env>(app: Hono<E>, config?: AppConfig) =>
|
|
|
169
210
|
if (!skipLogging) {
|
|
170
211
|
otel.logger.debug('%s %s started', c.req.method, c.req.path);
|
|
171
212
|
}
|
|
213
|
+
|
|
172
214
|
await next();
|
|
215
|
+
|
|
173
216
|
// Don't log completion for websocket upgrades - they stay open
|
|
174
217
|
if (!skipLogging && !isWebSocket) {
|
|
175
218
|
otel.logger.debug(
|
|
@@ -183,7 +226,7 @@ export const createServer = <E extends Env>(app: Hono<E>, config?: AppConfig) =>
|
|
|
183
226
|
});
|
|
184
227
|
|
|
185
228
|
// setup the cors middleware
|
|
186
|
-
|
|
229
|
+
router.use(
|
|
187
230
|
'*',
|
|
188
231
|
cors({
|
|
189
232
|
origin: config?.cors?.origin ?? ((origin) => origin),
|
|
@@ -202,23 +245,78 @@ export const createServer = <E extends Env>(app: Hono<E>, config?: AppConfig) =>
|
|
|
202
245
|
})
|
|
203
246
|
);
|
|
204
247
|
|
|
205
|
-
|
|
248
|
+
router.get('/_health', (c) => c.text('OK'));
|
|
249
|
+
router.route('/_agentuity', createAgentuityAPIs());
|
|
206
250
|
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
251
|
+
// Mount local storage router if using local services
|
|
252
|
+
if (servicesResult?.localRouter) {
|
|
253
|
+
router.route('/', servicesResult.localRouter);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// we create a middleware that attempts to match our routeid to the incoming route
|
|
257
|
+
let routeMapping: Record<string, string>;
|
|
258
|
+
const routePathMapper = createMiddleware<Env>(async (c, next) => {
|
|
259
|
+
if (!routeMapping) {
|
|
260
|
+
// Look for .routemapping.json in the project's .agentuity directory
|
|
261
|
+
// This is where the build plugin writes it (build.config.outdir)
|
|
262
|
+
const projectRoot = process.cwd();
|
|
263
|
+
const routeMappingPath = join(projectRoot, '.agentuity', '.routemapping.json');
|
|
264
|
+
const file = Bun.file(routeMappingPath);
|
|
265
|
+
if (!(await file.exists())) {
|
|
266
|
+
c.var.logger.fatal(
|
|
267
|
+
'error loading the .routemapping.json from the %s directory. this is a build issue!',
|
|
268
|
+
routeMappingPath
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
routeMapping = (await file.json()) as Record<string, string>;
|
|
272
|
+
}
|
|
273
|
+
const matches = matchedRoutes(c).filter(
|
|
274
|
+
(m) => m.method !== 'ALL' && (m.path.startsWith('/api') || m.path.startsWith('/agent/'))
|
|
275
|
+
);
|
|
276
|
+
const _c = privateContext(c);
|
|
277
|
+
if (matches.length > 0) {
|
|
278
|
+
const method = c.req.method.toLowerCase();
|
|
279
|
+
for (const m of matches) {
|
|
280
|
+
const found = routeMapping[`${method} ${m.path}`];
|
|
281
|
+
if (found) {
|
|
282
|
+
_c.set('routeId', found);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
_c.set('trigger', 'api'); // will get overwritten below if another trigger
|
|
288
|
+
return next();
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
router.use('/agent/*', routePathMapper);
|
|
292
|
+
router.use('/api/*', routePathMapper);
|
|
293
|
+
|
|
294
|
+
// Attach services and agent registry to context for API routes
|
|
295
|
+
router.use('/api/*', async (c, next) => {
|
|
296
|
+
const { createAgentMiddleware } = await import('./agent');
|
|
297
|
+
// Use a null agent name to just populate the agent registry without setting current agent
|
|
298
|
+
return createAgentMiddleware('')(c, next);
|
|
212
299
|
});
|
|
213
300
|
|
|
214
|
-
|
|
215
|
-
|
|
301
|
+
// set the trigger for specific types
|
|
302
|
+
for (const trigger of ['sms', 'email', 'cron'] as const) {
|
|
303
|
+
const middleware = createMiddleware(async (c, next) => {
|
|
304
|
+
const _c = privateContext(c);
|
|
305
|
+
_c.set('trigger', trigger);
|
|
306
|
+
await next();
|
|
307
|
+
});
|
|
308
|
+
router.use(`/api/${trigger}/*`, middleware);
|
|
309
|
+
router.use(`/agent/${trigger}/*`, middleware);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
router.use('/api/*', otelMiddleware);
|
|
313
|
+
router.use('/agent/*', otelMiddleware);
|
|
216
314
|
|
|
217
315
|
const shutdown = async () => {
|
|
218
316
|
if (isShutdown) {
|
|
219
317
|
return;
|
|
220
318
|
}
|
|
221
|
-
otel.logger.
|
|
319
|
+
otel.logger.debug('shutdown started');
|
|
222
320
|
isShutdown = true;
|
|
223
321
|
// Force exit after timeout if cleanup hangs
|
|
224
322
|
const forceExitTimer = setTimeout(() => {
|
|
@@ -228,7 +326,7 @@ export const createServer = <E extends Env>(app: Hono<E>, config?: AppConfig) =>
|
|
|
228
326
|
try {
|
|
229
327
|
await server.stop();
|
|
230
328
|
await otel.shutdown();
|
|
231
|
-
otel.logger.
|
|
329
|
+
otel.logger.debug('shutdown completed');
|
|
232
330
|
} finally {
|
|
233
331
|
clearTimeout(forceExitTimer);
|
|
234
332
|
}
|
|
@@ -269,10 +367,11 @@ const createAgentuityAPIs = () => {
|
|
|
269
367
|
const router = new Hono<Env>();
|
|
270
368
|
router.get('idle', (c) => {
|
|
271
369
|
if (isIdle()) {
|
|
272
|
-
return
|
|
370
|
+
return c.text('OK', { status: 200 });
|
|
273
371
|
}
|
|
274
|
-
return
|
|
372
|
+
return c.text('NO', { status: 200 });
|
|
275
373
|
});
|
|
374
|
+
router.get('health', (c) => c.text('OK'));
|
|
276
375
|
return router;
|
|
277
376
|
};
|
|
278
377
|
|
|
@@ -282,11 +381,15 @@ const otelMiddleware = createMiddleware<Env>(async (c, next) => {
|
|
|
282
381
|
|
|
283
382
|
const method = c.req.method;
|
|
284
383
|
const url = new URL(c.req.url);
|
|
384
|
+
const threadProvider = getThreadProvider();
|
|
385
|
+
const sessionProvider = getSessionProvider();
|
|
386
|
+
const sessionEventProvider = getSessionEventProvider();
|
|
285
387
|
|
|
286
388
|
// Execute the request handler within the extracted context
|
|
287
389
|
await context.with(extractedContext, async (): Promise<void> => {
|
|
288
390
|
// Create a span for this incoming request
|
|
289
|
-
|
|
391
|
+
const tracer = trace.getTracer('http-server');
|
|
392
|
+
await tracer.startActiveSpan(
|
|
290
393
|
`HTTP ${method}`,
|
|
291
394
|
{
|
|
292
395
|
kind: SpanKind.SERVER,
|
|
@@ -298,11 +401,126 @@ const otelMiddleware = createMiddleware<Env>(async (c, next) => {
|
|
|
298
401
|
},
|
|
299
402
|
},
|
|
300
403
|
async (span): Promise<void> => {
|
|
404
|
+
const sctx = span.spanContext();
|
|
405
|
+
const sessionId = sctx?.traceId ? `sess_${sctx.traceId}` : generateId('sess');
|
|
406
|
+
|
|
407
|
+
// Add to tracestate
|
|
408
|
+
let traceState = sctx.traceState ?? new TraceState();
|
|
409
|
+
const projectId = runtimeConfig.getProjectId();
|
|
410
|
+
const orgId = runtimeConfig.getOrganizationId();
|
|
411
|
+
const deploymentId = runtimeConfig.getDeploymentId();
|
|
412
|
+
const isDevMode = runtimeConfig.isDevMode();
|
|
413
|
+
if (projectId) {
|
|
414
|
+
traceState = traceState.set('pid', projectId);
|
|
415
|
+
}
|
|
416
|
+
if (orgId) {
|
|
417
|
+
traceState = traceState.set('oid', orgId);
|
|
418
|
+
}
|
|
419
|
+
if (isDevMode) {
|
|
420
|
+
traceState = traceState.set('d', '1');
|
|
421
|
+
}
|
|
422
|
+
sctx.traceState = traceState;
|
|
423
|
+
|
|
424
|
+
const thread = await threadProvider.restore(c as unknown as HonoContext<Env>);
|
|
425
|
+
const session = await sessionProvider.restore(thread, sessionId);
|
|
426
|
+
const handler = new WaitUntilHandler(tracer);
|
|
427
|
+
|
|
428
|
+
const _c = privateContext(c);
|
|
429
|
+
const agentIds = new Set<string>();
|
|
430
|
+
_c.set('agentIds', agentIds);
|
|
431
|
+
|
|
432
|
+
const shouldSendSession = orgId && projectId && _c.var.routeId;
|
|
433
|
+
let canSendSessionEvents = true;
|
|
434
|
+
|
|
435
|
+
if (shouldSendSession) {
|
|
436
|
+
await sessionEventProvider
|
|
437
|
+
.start({
|
|
438
|
+
id: sessionId,
|
|
439
|
+
orgId,
|
|
440
|
+
projectId,
|
|
441
|
+
threadId: thread.id,
|
|
442
|
+
routeId: _c.var.routeId,
|
|
443
|
+
deploymentId,
|
|
444
|
+
devmode: isDevMode,
|
|
445
|
+
environment: runtimeConfig.getEnvironment(),
|
|
446
|
+
method: c.req.method,
|
|
447
|
+
url: c.req.url,
|
|
448
|
+
trigger: _c.var.trigger,
|
|
449
|
+
})
|
|
450
|
+
.catch((ex) => {
|
|
451
|
+
canSendSessionEvents = false;
|
|
452
|
+
c.var.logger.error('error sending session start event: %s', ex);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
c.set('sessionId', sessionId);
|
|
457
|
+
c.set('thread', thread);
|
|
458
|
+
c.set('session', session);
|
|
459
|
+
_c.set('waitUntilHandler', handler);
|
|
460
|
+
|
|
461
|
+
let hasPendingWaits = false;
|
|
462
|
+
|
|
301
463
|
try {
|
|
302
464
|
await next();
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
465
|
+
if (handler?.hasPending()) {
|
|
466
|
+
hasPendingWaits = true;
|
|
467
|
+
handler
|
|
468
|
+
.waitUntilAll(c.var.logger, sessionId)
|
|
469
|
+
.then(async () => {
|
|
470
|
+
c.var.logger.debug('wait until finished for session %s', sessionId);
|
|
471
|
+
await sessionProvider.save(session);
|
|
472
|
+
await threadProvider.save(thread);
|
|
473
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
474
|
+
if (shouldSendSession && canSendSessionEvents) {
|
|
475
|
+
sessionEventProvider
|
|
476
|
+
.complete({
|
|
477
|
+
id: sessionId,
|
|
478
|
+
statusCode: c.res.status,
|
|
479
|
+
agentIds: Array.from(agentIds),
|
|
480
|
+
})
|
|
481
|
+
.then(() => {})
|
|
482
|
+
.catch((ex) => c.var.logger.error(ex));
|
|
483
|
+
}
|
|
484
|
+
})
|
|
485
|
+
.catch((ex) => {
|
|
486
|
+
c.var.logger.error('wait until errored for session %s. %s', sessionId, ex);
|
|
487
|
+
if (ex instanceof Error) {
|
|
488
|
+
span.recordException(ex);
|
|
489
|
+
}
|
|
490
|
+
const message = (ex as Error).message ?? String(ex);
|
|
491
|
+
span.setStatus({
|
|
492
|
+
code: SpanStatusCode.ERROR,
|
|
493
|
+
message,
|
|
494
|
+
});
|
|
495
|
+
c.var.logger.error(message);
|
|
496
|
+
if (shouldSendSession && canSendSessionEvents) {
|
|
497
|
+
sessionEventProvider
|
|
498
|
+
.complete({
|
|
499
|
+
id: sessionId,
|
|
500
|
+
statusCode: c.res.status,
|
|
501
|
+
error: message,
|
|
502
|
+
agentIds: Array.from(agentIds),
|
|
503
|
+
})
|
|
504
|
+
.then(() => {})
|
|
505
|
+
.catch((ex) => c.var.logger.error(ex));
|
|
506
|
+
}
|
|
507
|
+
})
|
|
508
|
+
.finally(() => {
|
|
509
|
+
span.end();
|
|
510
|
+
});
|
|
511
|
+
} else {
|
|
512
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
513
|
+
if (shouldSendSession && canSendSessionEvents) {
|
|
514
|
+
sessionEventProvider
|
|
515
|
+
.complete({
|
|
516
|
+
id: sessionId,
|
|
517
|
+
statusCode: c.res.status,
|
|
518
|
+
agentIds: Array.from(agentIds),
|
|
519
|
+
})
|
|
520
|
+
.then(() => {})
|
|
521
|
+
.catch((ex) => c.var.logger.error(ex));
|
|
522
|
+
}
|
|
523
|
+
}
|
|
306
524
|
} catch (ex) {
|
|
307
525
|
if (ex instanceof Error) {
|
|
308
526
|
span.recordException(ex);
|
|
@@ -312,10 +530,34 @@ const otelMiddleware = createMiddleware<Env>(async (c, next) => {
|
|
|
312
530
|
code: SpanStatusCode.ERROR,
|
|
313
531
|
message,
|
|
314
532
|
});
|
|
315
|
-
c.var.logger.error(
|
|
533
|
+
c.var.logger.error(message);
|
|
534
|
+
if (shouldSendSession && canSendSessionEvents) {
|
|
535
|
+
sessionEventProvider
|
|
536
|
+
.complete({
|
|
537
|
+
id: sessionId,
|
|
538
|
+
statusCode: c.res.status,
|
|
539
|
+
error: message,
|
|
540
|
+
agentIds: Array.from(agentIds),
|
|
541
|
+
})
|
|
542
|
+
.then(() => {})
|
|
543
|
+
.catch((ex) => c.var.logger.error(ex));
|
|
544
|
+
}
|
|
316
545
|
throw ex;
|
|
317
546
|
} finally {
|
|
318
|
-
|
|
547
|
+
// add otel headers into HTTP response
|
|
548
|
+
const headers: Record<string, string> = {};
|
|
549
|
+
propagation.inject(context.active(), headers);
|
|
550
|
+
for (const key of Object.keys(headers)) {
|
|
551
|
+
c.header(key, headers[key]);
|
|
552
|
+
}
|
|
553
|
+
if (!hasPendingWaits) {
|
|
554
|
+
try {
|
|
555
|
+
await sessionProvider.save(session);
|
|
556
|
+
await threadProvider.save(thread);
|
|
557
|
+
} finally {
|
|
558
|
+
span.end();
|
|
559
|
+
}
|
|
560
|
+
}
|
|
319
561
|
}
|
|
320
562
|
}
|
|
321
563
|
);
|