@lobu/gateway 3.0.8 → 3.0.9

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.
@@ -49,53 +49,57 @@ class UnifiedThreadResponseConsumer {
49
49
  * Handle a thread response job by routing to the appropriate platform renderer.
50
50
  */
51
51
  async handleThreadResponse(job) {
52
- var _a, _b;
52
+ var _a, _b, _c;
53
53
  const data = job.data;
54
54
  if (!data || !data.messageId) {
55
55
  logger.error(`Invalid thread response data: ${JSON.stringify(data)}`);
56
56
  return;
57
57
  }
58
- // Check if this response belongs to a Chat SDK connection — handle before legacy routing
59
- if ((_a = this.chatResponseBridge) === null || _a === void 0 ? void 0 : _a.canHandle(data)) {
60
- const sessionKey = `${data.userId}:${data.originalMessageId || data.messageId}`;
61
- try {
58
+ // Create child span for response processing (linked to original trace)
59
+ const traceparent = (_a = data.platformMetadata) === null || _a === void 0 ? void 0 : _a.traceparent;
60
+ const span = (0, core_1.createChildSpan)("response_delivery", traceparent, {
61
+ "lobu.message_id": data.messageId,
62
+ "lobu.user_id": data.userId,
63
+ "lobu.platform": data.platform || data.teamId || "unknown",
64
+ });
65
+ try {
66
+ // Check if this response belongs to a Chat SDK connection — handle before legacy routing
67
+ if ((_b = this.chatResponseBridge) === null || _b === void 0 ? void 0 : _b.canHandle(data)) {
68
+ const sessionKey = `${data.userId}:${data.originalMessageId || data.messageId}`;
62
69
  await this.routeToRenderer(this.chatResponseBridge, data, sessionKey);
70
+ return;
63
71
  }
64
- catch (error) {
65
- logger.error("Error processing Chat SDK response:", error);
66
- throw error;
72
+ // Use platform field, fall back to teamId
73
+ const platformName = data.platform || data.teamId;
74
+ if (!platformName) {
75
+ logger.warn(`Missing platform in thread response for message ${data.messageId}, skipping`);
76
+ return;
67
77
  }
68
- return;
69
- }
70
- // Use platform field, fall back to teamId
71
- const platformName = data.platform || data.teamId;
72
- if (!platformName) {
73
- logger.warn(`Missing platform in thread response for message ${data.messageId}, skipping`);
74
- return;
75
- }
76
- // Get platform adapter from registry
77
- const platform = this.platformRegistry.get(platformName);
78
- if (!platform) {
79
- logger.warn(`No platform adapter registered for: ${platformName}, skipping message ${data.messageId}`);
80
- return;
81
- }
82
- // Get renderer from platform
83
- const renderer = (_b = platform.getResponseRenderer) === null || _b === void 0 ? void 0 : _b.call(platform);
84
- if (!renderer) {
85
- logger.warn(`Platform ${platformName} does not provide a response renderer, skipping message ${data.messageId}`);
86
- return;
87
- }
88
- // Create session key for tracking
89
- const sessionKey = `${data.userId}:${data.originalMessageId || data.messageId}`;
90
- logger.info(`Processing thread response for platform=${platformName}, message=${data.messageId}, session=${sessionKey}`);
91
- try {
78
+ // Get platform adapter from registry
79
+ const platform = this.platformRegistry.get(platformName);
80
+ if (!platform) {
81
+ logger.warn(`No platform adapter registered for: ${platformName}, skipping message ${data.messageId}`);
82
+ return;
83
+ }
84
+ // Get renderer from platform
85
+ const renderer = (_c = platform.getResponseRenderer) === null || _c === void 0 ? void 0 : _c.call(platform);
86
+ if (!renderer) {
87
+ logger.warn(`Platform ${platformName} does not provide a response renderer, skipping message ${data.messageId}`);
88
+ return;
89
+ }
90
+ // Create session key for tracking
91
+ const sessionKey = `${data.userId}:${data.originalMessageId || data.messageId}`;
92
+ logger.info(`Processing thread response for platform=${platformName}, message=${data.messageId}, session=${sessionKey}`);
92
93
  await this.routeToRenderer(renderer, data, sessionKey);
93
94
  }
94
95
  catch (error) {
95
- logger.error(`Error processing thread response for ${platformName}:`, error);
96
- // Let queue handle retry logic
96
+ logger.error(`Error processing thread response for message ${data.messageId}:`, error);
97
97
  throw error;
98
98
  }
99
+ finally {
100
+ span === null || span === void 0 ? void 0 : span.end();
101
+ void (0, core_1.flushTracing)();
102
+ }
99
103
  }
100
104
  /**
101
105
  * Route the payload to the appropriate renderer method.
@@ -1 +1 @@
1
- {"version":3,"file":"unified-thread-consumer.js","sourceRoot":"","sources":["../../src/platform/unified-thread-consumer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"unified-thread-consumer.js","sourceRoot":"","sources":["../../src/platform/unified-thread-consumer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobu/gateway",
3
- "version": "3.0.8",
3
+ "version": "3.0.9",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Lobu SDK — embed AI agents with platform adapters, worker orchestration, and MCP proxy",
6
6
  "main": "dist/index.js",
@@ -22,13 +22,6 @@
22
22
  "require": "./dist/api/index.js"
23
23
  }
24
24
  },
25
- "scripts": {
26
- "build": "tsc",
27
- "dev": "DEPLOYMENT_MODE=docker bun --watch src/index.ts -- --env ../../.env",
28
- "start": "cd ../core && bun run build && cd ../gateway && bun src/index.ts",
29
- "test": "bun test",
30
- "typecheck": "tsc --noEmit"
31
- },
32
25
  "dependencies": {
33
26
  "@aws-sdk/client-bedrock": "^3.1028.0",
34
27
  "@chat-adapter/discord": "^4",
@@ -41,7 +34,7 @@
41
34
  "@hono/node-server": "^1.19.9",
42
35
  "@hono/zod-openapi": "^1.2.1",
43
36
  "@kubernetes/client-node": "0.21.0",
44
- "@lobu/core": "workspace:*",
37
+ "@lobu/core": "^3.0.5",
45
38
  "@mariozechner/pi-ai": "^0.51.6",
46
39
  "@scalar/hono-api-reference": "^0.9.39",
47
40
  "@sentry/node": "^10.19.0",
@@ -61,5 +54,12 @@
61
54
  "@types/dockerode": "^3.3.29",
62
55
  "@types/node": "^20.0.0",
63
56
  "typescript": "^5.8.3"
57
+ },
58
+ "scripts": {
59
+ "build": "tsc",
60
+ "dev": "DEPLOYMENT_MODE=docker bun --watch src/index.ts -- --env ../../.env",
61
+ "start": "cd ../core && bun run build && cd ../gateway && bun src/index.ts",
62
+ "test": "bun test",
63
+ "typecheck": "tsc --noEmit"
64
64
  }
65
- }
65
+ }
package/src/cli/index.ts CHANGED
@@ -34,8 +34,8 @@ async function main() {
34
34
  initTracing({
35
35
  serviceName: "lobu-gateway",
36
36
  serviceVersion: process.env.npm_package_version || "2.0.0",
37
- tempoEndpoint: process.env.TEMPO_ENDPOINT,
38
- enabled: !!process.env.TEMPO_ENDPOINT,
37
+ otlpEndpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
38
+ enabled: !!process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
39
39
  });
40
40
 
41
41
  const config = buildGatewayConfig();
@@ -4,7 +4,12 @@
4
4
  * settings links, allowlist, audio transcription, etc.
5
5
  */
6
6
 
7
- import { createLogger, generateTraceId } from "@lobu/core";
7
+ import {
8
+ createLogger,
9
+ createRootSpan,
10
+ flushTracing,
11
+ generateTraceId,
12
+ } from "@lobu/core";
8
13
  import type Redis from "ioredis";
9
14
  import type { CommandDispatcher } from "../commands/command-dispatcher";
10
15
  import { createChatReply } from "../commands/command-reply-adapters";
@@ -290,62 +295,82 @@ class MessageHandlerBridge {
290
295
  const traceId = generateTraceId(messageId);
291
296
  const agentSettingsStore = this.services.getAgentSettingsStore();
292
297
 
293
- // Check if agent has any provider credentials before enqueuing
294
- if (!(await hasConfiguredProvider(agentId, agentSettingsStore))) {
295
- await thread.post(
296
- "No AI provider is configured yet. Provider setup is not available in the end-user chat flow yet. Ask an admin to connect a provider for the base agent."
297
- );
298
- return;
299
- }
298
+ // Create root span for distributed tracing
299
+ const { span: rootSpan, traceparent } = createRootSpan("message_received", {
300
+ "lobu.agent_id": agentId,
301
+ "lobu.message_id": messageId,
302
+ "lobu.platform": platform,
303
+ "lobu.connection_id": this.connection.id,
304
+ });
300
305
 
301
- const agentOptions = await resolveAgentOptions(
302
- agentId,
303
- {},
304
- agentSettingsStore
305
- );
306
+ try {
307
+ // Check if agent has any provider credentials before enqueuing
308
+ if (!(await hasConfiguredProvider(agentId, agentSettingsStore))) {
309
+ await thread.post(
310
+ "No AI provider is configured yet. Provider setup is not available in the end-user chat flow yet. Ask an admin to connect a provider for the base agent."
311
+ );
312
+ return;
313
+ }
306
314
 
307
- const payload = buildMessagePayload({
308
- platform,
309
- userId,
310
- botId: platform,
311
- conversationId: isGroup ? messageId : channelId,
312
- teamId: isGroup ? channelId : platform,
313
- agentId,
314
- messageId,
315
- messageText,
316
- channelId,
317
- platformMetadata: {
318
- traceId,
315
+ const agentOptions = await resolveAgentOptions(
319
316
  agentId,
320
- chatId: channelId,
321
- senderId: userId,
322
- senderUsername: message.author?.userName,
323
- senderDisplayName: message.author?.fullName,
324
- isGroup,
325
- connectionId: this.connection.id,
326
- responseChannel: channelId,
327
- responseId: messageId,
328
- responseThreadId: thread.id,
329
- conversationHistory:
330
- conversationHistory.length > 0 ? conversationHistory : undefined,
331
- ...(sessionReset && { sessionReset: true }),
332
- },
333
- agentOptions,
334
- });
317
+ {},
318
+ agentSettingsStore
319
+ );
335
320
 
336
- const queueProducer = this.services.getQueueProducer();
337
- await queueProducer.enqueueMessage(payload);
321
+ const payload = buildMessagePayload({
322
+ platform,
323
+ userId,
324
+ botId: platform,
325
+ conversationId: isGroup ? messageId : channelId,
326
+ teamId: isGroup ? channelId : platform,
327
+ agentId,
328
+ messageId,
329
+ messageText,
330
+ channelId,
331
+ platformMetadata: {
332
+ traceId,
333
+ traceparent: traceparent || undefined,
334
+ agentId,
335
+ chatId: channelId,
336
+ senderId: userId,
337
+ senderUsername: message.author?.userName,
338
+ senderDisplayName: message.author?.fullName,
339
+ isGroup,
340
+ connectionId: this.connection.id,
341
+ responseChannel: channelId,
342
+ responseId: messageId,
343
+ responseThreadId: thread.id,
344
+ conversationHistory:
345
+ conversationHistory.length > 0 ? conversationHistory : undefined,
346
+ ...(sessionReset && { sessionReset: true }),
347
+ },
348
+ agentOptions,
349
+ });
350
+
351
+ const queueProducer = this.services.getQueueProducer();
352
+ await queueProducer.enqueueMessage(payload);
338
353
 
339
- logger.info(
340
- { traceId, messageId, agentId, connectionId: this.connection.id },
341
- "Message enqueued via Chat SDK bridge"
342
- );
354
+ logger.info(
355
+ {
356
+ traceId,
357
+ traceparent,
358
+ messageId,
359
+ agentId,
360
+ connectionId: this.connection.id,
361
+ },
362
+ "Message enqueued via Chat SDK bridge"
363
+ );
343
364
 
344
- // Show typing indicator
345
- try {
346
- await thread.startTyping?.("Processing...");
347
- } catch {
348
- // best effort
365
+ // Show typing indicator
366
+ try {
367
+ await thread.startTyping?.("Processing...");
368
+ } catch {
369
+ // best effort
370
+ }
371
+ } finally {
372
+ rootSpan?.end();
373
+ void flushTracing();
349
374
  }
350
375
  }
351
376
 
@@ -480,15 +480,15 @@ export abstract class BaseDeploymentManager {
480
480
  envVars.TRACE_ID = traceId;
481
481
  }
482
482
 
483
- // Add Tempo endpoint for distributed tracing
484
- const tempoEndpoint = process.env.TEMPO_ENDPOINT;
485
- if (tempoEndpoint) {
486
- envVars.TEMPO_ENDPOINT = tempoEndpoint;
483
+ // Add OTLP endpoint for distributed tracing
484
+ const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
485
+ if (otlpEndpoint) {
486
+ envVars.OTEL_EXPORTER_OTLP_ENDPOINT = otlpEndpoint;
487
487
  try {
488
- const tempoUrl = new URL(tempoEndpoint);
489
- envVars.NO_PROXY = `${envVars.NO_PROXY},${tempoUrl.hostname}`;
488
+ const otlpUrl = new URL(otlpEndpoint);
489
+ envVars.NO_PROXY = `${envVars.NO_PROXY},${otlpUrl.hostname}`;
490
490
  } catch {
491
- envVars.NO_PROXY = `${envVars.NO_PROXY},lobu-tempo`;
491
+ envVars.NO_PROXY = `${envVars.NO_PROXY},tempo`;
492
492
  }
493
493
  }
494
494
 
@@ -4,7 +4,7 @@
4
4
  * via the PlatformRegistry, eliminating duplicate queue filtering logic.
5
5
  */
6
6
 
7
- import { createLogger } from "@lobu/core";
7
+ import { createChildSpan, createLogger, flushTracing } from "@lobu/core";
8
8
  import type { ChatResponseBridge } from "../connections/chat-response-bridge";
9
9
  import type {
10
10
  IMessageQueue,
@@ -77,61 +77,68 @@ export class UnifiedThreadResponseConsumer {
77
77
  return;
78
78
  }
79
79
 
80
- // Check if this response belongs to a Chat SDK connection — handle before legacy routing
81
- if (this.chatResponseBridge?.canHandle(data)) {
82
- const sessionKey = `${data.userId}:${data.originalMessageId || data.messageId}`;
83
- try {
80
+ // Create child span for response processing (linked to original trace)
81
+ const traceparent = data.platformMetadata?.traceparent as
82
+ | string
83
+ | undefined;
84
+ const span = createChildSpan("response_delivery", traceparent, {
85
+ "lobu.message_id": data.messageId,
86
+ "lobu.user_id": data.userId,
87
+ "lobu.platform": data.platform || data.teamId || "unknown",
88
+ });
89
+
90
+ try {
91
+ // Check if this response belongs to a Chat SDK connection — handle before legacy routing
92
+ if (this.chatResponseBridge?.canHandle(data)) {
93
+ const sessionKey = `${data.userId}:${data.originalMessageId || data.messageId}`;
84
94
  await this.routeToRenderer(this.chatResponseBridge, data, sessionKey);
85
- } catch (error) {
86
- logger.error("Error processing Chat SDK response:", error);
87
- throw error;
95
+ return;
88
96
  }
89
- return;
90
- }
91
97
 
92
- // Use platform field, fall back to teamId
93
- const platformName = data.platform || data.teamId;
94
- if (!platformName) {
95
- logger.warn(
96
- `Missing platform in thread response for message ${data.messageId}, skipping`
97
- );
98
- return;
99
- }
98
+ // Use platform field, fall back to teamId
99
+ const platformName = data.platform || data.teamId;
100
+ if (!platformName) {
101
+ logger.warn(
102
+ `Missing platform in thread response for message ${data.messageId}, skipping`
103
+ );
104
+ return;
105
+ }
100
106
 
101
- // Get platform adapter from registry
102
- const platform = this.platformRegistry.get(platformName);
103
- if (!platform) {
104
- logger.warn(
105
- `No platform adapter registered for: ${platformName}, skipping message ${data.messageId}`
106
- );
107
- return;
108
- }
107
+ // Get platform adapter from registry
108
+ const platform = this.platformRegistry.get(platformName);
109
+ if (!platform) {
110
+ logger.warn(
111
+ `No platform adapter registered for: ${platformName}, skipping message ${data.messageId}`
112
+ );
113
+ return;
114
+ }
109
115
 
110
- // Get renderer from platform
111
- const renderer = platform.getResponseRenderer?.();
112
- if (!renderer) {
113
- logger.warn(
114
- `Platform ${platformName} does not provide a response renderer, skipping message ${data.messageId}`
115
- );
116
- return;
117
- }
116
+ // Get renderer from platform
117
+ const renderer = platform.getResponseRenderer?.();
118
+ if (!renderer) {
119
+ logger.warn(
120
+ `Platform ${platformName} does not provide a response renderer, skipping message ${data.messageId}`
121
+ );
122
+ return;
123
+ }
118
124
 
119
- // Create session key for tracking
120
- const sessionKey = `${data.userId}:${data.originalMessageId || data.messageId}`;
125
+ // Create session key for tracking
126
+ const sessionKey = `${data.userId}:${data.originalMessageId || data.messageId}`;
121
127
 
122
- logger.info(
123
- `Processing thread response for platform=${platformName}, message=${data.messageId}, session=${sessionKey}`
124
- );
128
+ logger.info(
129
+ `Processing thread response for platform=${platformName}, message=${data.messageId}, session=${sessionKey}`
130
+ );
125
131
 
126
- try {
127
132
  await this.routeToRenderer(renderer, data, sessionKey);
128
133
  } catch (error) {
129
134
  logger.error(
130
- `Error processing thread response for ${platformName}:`,
135
+ `Error processing thread response for message ${data.messageId}:`,
131
136
  error
132
137
  );
133
- // Let queue handle retry logic
134
138
  throw error;
139
+ } finally {
140
+ span?.end();
141
+ void flushTracing();
135
142
  }
136
143
  }
137
144