@lobu/gateway 3.0.9 → 3.0.13
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/api/platform.d.ts.map +1 -1
- package/dist/api/platform.js +7 -26
- package/dist/api/platform.js.map +1 -1
- package/dist/auth/mcp/proxy.d.ts +14 -0
- package/dist/auth/mcp/proxy.d.ts.map +1 -1
- package/dist/auth/mcp/proxy.js +149 -13
- package/dist/auth/mcp/proxy.js.map +1 -1
- package/dist/cli/gateway.d.ts.map +1 -1
- package/dist/cli/gateway.js +29 -0
- package/dist/cli/gateway.js.map +1 -1
- package/dist/connections/chat-instance-manager.d.ts.map +1 -1
- package/dist/connections/chat-instance-manager.js +2 -1
- package/dist/connections/chat-instance-manager.js.map +1 -1
- package/dist/connections/interaction-bridge.d.ts +9 -2
- package/dist/connections/interaction-bridge.d.ts.map +1 -1
- package/dist/connections/interaction-bridge.js +121 -261
- package/dist/connections/interaction-bridge.js.map +1 -1
- package/dist/gateway/index.js +1 -1
- package/dist/gateway/index.js.map +1 -1
- package/dist/interactions.d.ts +9 -43
- package/dist/interactions.d.ts.map +1 -1
- package/dist/interactions.js +10 -52
- package/dist/interactions.js.map +1 -1
- package/dist/routes/public/agent.d.ts +4 -0
- package/dist/routes/public/agent.d.ts.map +1 -1
- package/dist/routes/public/agent.js +21 -0
- package/dist/routes/public/agent.js.map +1 -1
- package/dist/services/core-services.d.ts.map +1 -1
- package/dist/services/core-services.js +4 -0
- package/dist/services/core-services.js.map +1 -1
- package/package.json +9 -9
- package/src/__tests__/agent-config-routes.test.ts +0 -254
- package/src/__tests__/agent-history-routes.test.ts +0 -72
- package/src/__tests__/agent-routes.test.ts +0 -68
- package/src/__tests__/agent-schedules-routes.test.ts +0 -59
- package/src/__tests__/agent-settings-store.test.ts +0 -323
- package/src/__tests__/bedrock-model-catalog.test.ts +0 -40
- package/src/__tests__/bedrock-openai-service.test.ts +0 -157
- package/src/__tests__/bedrock-provider-module.test.ts +0 -56
- package/src/__tests__/chat-instance-manager-slack.test.ts +0 -204
- package/src/__tests__/chat-response-bridge.test.ts +0 -131
- package/src/__tests__/config-memory-plugins.test.ts +0 -92
- package/src/__tests__/config-request-store.test.ts +0 -127
- package/src/__tests__/connection-routes.test.ts +0 -144
- package/src/__tests__/core-services-store-selection.test.ts +0 -92
- package/src/__tests__/docker-deployment.test.ts +0 -1211
- package/src/__tests__/embedded-deployment.test.ts +0 -342
- package/src/__tests__/grant-store.test.ts +0 -148
- package/src/__tests__/http-proxy.test.ts +0 -281
- package/src/__tests__/instruction-service.test.ts +0 -37
- package/src/__tests__/link-buttons.test.ts +0 -112
- package/src/__tests__/lobu.test.ts +0 -32
- package/src/__tests__/mcp-config-service.test.ts +0 -347
- package/src/__tests__/mcp-proxy.test.ts +0 -694
- package/src/__tests__/message-handler-bridge.test.ts +0 -17
- package/src/__tests__/model-selection.test.ts +0 -172
- package/src/__tests__/oauth-templates.test.ts +0 -39
- package/src/__tests__/platform-adapter-slack-send.test.ts +0 -114
- package/src/__tests__/platform-helpers-model-resolution.test.ts +0 -253
- package/src/__tests__/provider-inheritance.test.ts +0 -212
- package/src/__tests__/routes/cli-auth.test.ts +0 -337
- package/src/__tests__/routes/interactions.test.ts +0 -121
- package/src/__tests__/secret-proxy.test.ts +0 -85
- package/src/__tests__/session-manager.test.ts +0 -572
- package/src/__tests__/setup.ts +0 -133
- package/src/__tests__/skill-and-mcp-registry.test.ts +0 -203
- package/src/__tests__/slack-routes.test.ts +0 -161
- package/src/__tests__/system-config-resolver.test.ts +0 -75
- package/src/__tests__/system-message-limiter.test.ts +0 -89
- package/src/__tests__/system-skills-service.test.ts +0 -362
- package/src/__tests__/transcription-service.test.ts +0 -222
- package/src/__tests__/utils/rate-limiter.test.ts +0 -102
- package/src/__tests__/worker-connection-manager.test.ts +0 -497
- package/src/__tests__/worker-job-router.test.ts +0 -722
- package/src/api/index.ts +0 -1
- package/src/api/platform.ts +0 -292
- package/src/api/response-renderer.ts +0 -157
- package/src/auth/agent-metadata-store.ts +0 -168
- package/src/auth/api-auth-middleware.ts +0 -69
- package/src/auth/api-key-provider-module.ts +0 -213
- package/src/auth/base-provider-module.ts +0 -201
- package/src/auth/bedrock/provider-module.ts +0 -110
- package/src/auth/chatgpt/chatgpt-oauth-module.ts +0 -185
- package/src/auth/chatgpt/device-code-client.ts +0 -218
- package/src/auth/chatgpt/index.ts +0 -1
- package/src/auth/claude/oauth-module.ts +0 -280
- package/src/auth/cli/token-service.ts +0 -249
- package/src/auth/external/client.ts +0 -560
- package/src/auth/external/device-code-client.ts +0 -235
- package/src/auth/mcp/config-service.ts +0 -420
- package/src/auth/mcp/proxy.ts +0 -1086
- package/src/auth/mcp/string-substitution.ts +0 -17
- package/src/auth/mcp/tool-cache.ts +0 -90
- package/src/auth/oauth/base-client.ts +0 -267
- package/src/auth/oauth/client.ts +0 -153
- package/src/auth/oauth/credentials.ts +0 -7
- package/src/auth/oauth/providers.ts +0 -69
- package/src/auth/oauth/state-store.ts +0 -150
- package/src/auth/oauth-templates.ts +0 -179
- package/src/auth/provider-catalog.ts +0 -220
- package/src/auth/provider-model-options.ts +0 -41
- package/src/auth/settings/agent-settings-store.ts +0 -565
- package/src/auth/settings/auth-profiles-manager.ts +0 -216
- package/src/auth/settings/index.ts +0 -12
- package/src/auth/settings/model-preference-store.ts +0 -52
- package/src/auth/settings/model-selection.ts +0 -135
- package/src/auth/settings/resolved-settings-view.ts +0 -298
- package/src/auth/settings/template-utils.ts +0 -44
- package/src/auth/settings/token-service.ts +0 -88
- package/src/auth/system-env-store.ts +0 -98
- package/src/auth/user-agents-store.ts +0 -68
- package/src/channels/binding-service.ts +0 -214
- package/src/channels/index.ts +0 -4
- package/src/cli/gateway.ts +0 -1312
- package/src/cli/index.ts +0 -74
- package/src/commands/built-in-commands.ts +0 -80
- package/src/commands/command-dispatcher.ts +0 -94
- package/src/commands/command-reply-adapters.ts +0 -27
- package/src/config/file-loader.ts +0 -618
- package/src/config/index.ts +0 -588
- package/src/config/network-allowlist.ts +0 -71
- package/src/connections/chat-instance-manager.ts +0 -1284
- package/src/connections/chat-response-bridge.ts +0 -618
- package/src/connections/index.ts +0 -7
- package/src/connections/interaction-bridge.ts +0 -831
- package/src/connections/message-handler-bridge.ts +0 -440
- package/src/connections/platform-auth-methods.ts +0 -15
- package/src/connections/types.ts +0 -84
- package/src/gateway/connection-manager.ts +0 -291
- package/src/gateway/index.ts +0 -698
- package/src/gateway/job-router.ts +0 -201
- package/src/gateway-main.ts +0 -200
- package/src/index.ts +0 -41
- package/src/infrastructure/queue/index.ts +0 -12
- package/src/infrastructure/queue/queue-producer.ts +0 -148
- package/src/infrastructure/queue/redis-queue.ts +0 -361
- package/src/infrastructure/queue/types.ts +0 -133
- package/src/infrastructure/redis/system-message-limiter.ts +0 -94
- package/src/interactions/config-request-store.ts +0 -198
- package/src/interactions.ts +0 -363
- package/src/lobu.ts +0 -311
- package/src/metrics/prometheus.ts +0 -159
- package/src/modules/module-system.ts +0 -179
- package/src/orchestration/base-deployment-manager.ts +0 -900
- package/src/orchestration/deployment-utils.ts +0 -98
- package/src/orchestration/impl/docker-deployment.ts +0 -620
- package/src/orchestration/impl/embedded-deployment.ts +0 -268
- package/src/orchestration/impl/index.ts +0 -8
- package/src/orchestration/impl/k8s/deployment.ts +0 -1061
- package/src/orchestration/impl/k8s/helpers.ts +0 -610
- package/src/orchestration/impl/k8s/index.ts +0 -1
- package/src/orchestration/index.ts +0 -333
- package/src/orchestration/message-consumer.ts +0 -584
- package/src/orchestration/scheduled-wakeup.ts +0 -704
- package/src/permissions/approval-policy.ts +0 -36
- package/src/permissions/grant-store.ts +0 -219
- package/src/platform/file-handler.ts +0 -66
- package/src/platform/link-buttons.ts +0 -57
- package/src/platform/renderer-utils.ts +0 -44
- package/src/platform/response-renderer.ts +0 -84
- package/src/platform/unified-thread-consumer.ts +0 -194
- package/src/platform.ts +0 -318
- package/src/proxy/http-proxy.ts +0 -752
- package/src/proxy/proxy-manager.ts +0 -81
- package/src/proxy/secret-proxy.ts +0 -402
- package/src/proxy/token-refresh-job.ts +0 -143
- package/src/routes/internal/audio.ts +0 -141
- package/src/routes/internal/device-auth.ts +0 -652
- package/src/routes/internal/files.ts +0 -226
- package/src/routes/internal/history.ts +0 -69
- package/src/routes/internal/images.ts +0 -127
- package/src/routes/internal/interactions.ts +0 -84
- package/src/routes/internal/middleware.ts +0 -23
- package/src/routes/internal/schedule.ts +0 -226
- package/src/routes/internal/types.ts +0 -22
- package/src/routes/openapi-auto.ts +0 -239
- package/src/routes/public/agent-access.ts +0 -23
- package/src/routes/public/agent-config.ts +0 -675
- package/src/routes/public/agent-history.ts +0 -422
- package/src/routes/public/agent-schedules.ts +0 -296
- package/src/routes/public/agent.ts +0 -1086
- package/src/routes/public/agents.ts +0 -373
- package/src/routes/public/channels.ts +0 -191
- package/src/routes/public/cli-auth.ts +0 -896
- package/src/routes/public/connections.ts +0 -574
- package/src/routes/public/landing.ts +0 -16
- package/src/routes/public/oauth.ts +0 -147
- package/src/routes/public/settings-auth.ts +0 -104
- package/src/routes/public/slack.ts +0 -173
- package/src/routes/shared/agent-ownership.ts +0 -101
- package/src/routes/shared/token-verifier.ts +0 -34
- package/src/services/bedrock-model-catalog.ts +0 -217
- package/src/services/bedrock-openai-service.ts +0 -658
- package/src/services/core-services.ts +0 -1072
- package/src/services/image-generation-service.ts +0 -257
- package/src/services/instruction-service.ts +0 -318
- package/src/services/mcp-registry.ts +0 -94
- package/src/services/platform-helpers.ts +0 -287
- package/src/services/session-manager.ts +0 -262
- package/src/services/settings-resolver.ts +0 -74
- package/src/services/system-config-resolver.ts +0 -89
- package/src/services/system-skills-service.ts +0 -229
- package/src/services/transcription-service.ts +0 -684
- package/src/session.ts +0 -110
- package/src/spaces/index.ts +0 -1
- package/src/spaces/space-resolver.ts +0 -17
- package/src/stores/in-memory-agent-store.ts +0 -403
- package/src/stores/redis-agent-store.ts +0 -279
- package/src/utils/public-url.ts +0 -44
- package/src/utils/rate-limiter.ts +0 -94
- package/tsconfig.json +0 -33
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,440 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Message handler bridge — connects Chat SDK events to the message queue.
|
|
3
|
-
* Bridges all 9 feature gaps: history, agent auto-creation, provider setup,
|
|
4
|
-
* settings links, allowlist, audio transcription, etc.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
createLogger,
|
|
9
|
-
createRootSpan,
|
|
10
|
-
flushTracing,
|
|
11
|
-
generateTraceId,
|
|
12
|
-
} from "@lobu/core";
|
|
13
|
-
import type Redis from "ioredis";
|
|
14
|
-
import type { CommandDispatcher } from "../commands/command-dispatcher";
|
|
15
|
-
import { createChatReply } from "../commands/command-reply-adapters";
|
|
16
|
-
import type { CoreServices } from "../platform";
|
|
17
|
-
import {
|
|
18
|
-
buildMessagePayload,
|
|
19
|
-
hasConfiguredProvider,
|
|
20
|
-
resolveAgentId,
|
|
21
|
-
resolveAgentOptions,
|
|
22
|
-
} from "../services/platform-helpers";
|
|
23
|
-
import type { ChatInstanceManager } from "./chat-instance-manager";
|
|
24
|
-
import type { PlatformConnection } from "./types";
|
|
25
|
-
|
|
26
|
-
const logger = createLogger("chat-message-bridge");
|
|
27
|
-
|
|
28
|
-
const MAX_HISTORY_MESSAGES = 10;
|
|
29
|
-
const HISTORY_TTL_SECONDS = 86400; // 24 hours
|
|
30
|
-
|
|
31
|
-
interface HistoryEntry {
|
|
32
|
-
role: "user" | "assistant";
|
|
33
|
-
content: string;
|
|
34
|
-
authorName?: string;
|
|
35
|
-
timestamp: number;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function isSenderAllowed(
|
|
39
|
-
allowFrom: string[] | undefined,
|
|
40
|
-
userId: string
|
|
41
|
-
): boolean {
|
|
42
|
-
if (!Array.isArray(allowFrom)) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
return allowFrom.includes(userId);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Register Chat SDK event handlers for a connection.
|
|
50
|
-
*/
|
|
51
|
-
export function registerMessageHandlers(
|
|
52
|
-
chat: any,
|
|
53
|
-
connection: PlatformConnection,
|
|
54
|
-
services: CoreServices,
|
|
55
|
-
manager: ChatInstanceManager,
|
|
56
|
-
commandDispatcher?: CommandDispatcher
|
|
57
|
-
): void {
|
|
58
|
-
const handler = new MessageHandlerBridge(
|
|
59
|
-
connection,
|
|
60
|
-
services,
|
|
61
|
-
manager,
|
|
62
|
-
commandDispatcher
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
chat.onNewMention(async (thread: any, message: any) => {
|
|
66
|
-
await handler.handleMessage(thread, message, "mention");
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
chat.onDirectMessage(async (thread: any, message: any) => {
|
|
70
|
-
await handler.handleMessage(thread, message, "dm");
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
chat.onSubscribedMessage(async (thread: any, message: any) => {
|
|
74
|
-
await handler.handleMessage(thread, message, "subscribed");
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
class MessageHandlerBridge {
|
|
79
|
-
private redis: Redis;
|
|
80
|
-
|
|
81
|
-
constructor(
|
|
82
|
-
private connection: PlatformConnection,
|
|
83
|
-
private services: CoreServices,
|
|
84
|
-
private manager: ChatInstanceManager,
|
|
85
|
-
private commandDispatcher?: CommandDispatcher
|
|
86
|
-
) {
|
|
87
|
-
this.redis = services.getQueue().getRedisClient();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async handleMessage(
|
|
91
|
-
thread: any,
|
|
92
|
-
message: any,
|
|
93
|
-
source: "mention" | "dm" | "subscribed"
|
|
94
|
-
): Promise<void> {
|
|
95
|
-
const { connection } = this;
|
|
96
|
-
|
|
97
|
-
// Guard: drop messages if the connection was stopped/removed
|
|
98
|
-
if (!this.manager.has(connection.id)) {
|
|
99
|
-
logger.info(
|
|
100
|
-
{ connectionId: connection.id },
|
|
101
|
-
"Connection no longer active, dropping message"
|
|
102
|
-
);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const platform = connection.platform;
|
|
107
|
-
const userId = message.author?.userId ?? "unknown";
|
|
108
|
-
const channelId = thread.channelId ?? thread.id ?? "unknown";
|
|
109
|
-
const messageId = message.id ?? String(Date.now());
|
|
110
|
-
const isGroup = source === "mention" || source === "subscribed";
|
|
111
|
-
|
|
112
|
-
logger.info(
|
|
113
|
-
{
|
|
114
|
-
connectionId: connection.id,
|
|
115
|
-
platform,
|
|
116
|
-
userId,
|
|
117
|
-
channelId,
|
|
118
|
-
messageId,
|
|
119
|
-
source,
|
|
120
|
-
},
|
|
121
|
-
"Processing inbound message"
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
// Gap 6: Allowlist check
|
|
125
|
-
if (!isSenderAllowed(connection.settings?.allowFrom, userId)) {
|
|
126
|
-
logger.info({ userId }, "Blocked by allowlist");
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Gap 6: Group check
|
|
131
|
-
if (isGroup && connection.settings?.allowGroups === false) {
|
|
132
|
-
logger.info({ channelId }, "Groups not allowed");
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Subscribe to thread for follow-up messages
|
|
137
|
-
if (source === "mention" || source === "dm") {
|
|
138
|
-
try {
|
|
139
|
-
await thread.subscribe();
|
|
140
|
-
} catch {
|
|
141
|
-
// some platforms may not support subscribe
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Gap 2: Resolve agent ID
|
|
146
|
-
const { agentId } = await resolveAgentId({
|
|
147
|
-
platform,
|
|
148
|
-
userId,
|
|
149
|
-
channelId,
|
|
150
|
-
isGroup,
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
// Gap 2: Auto-create agent metadata
|
|
154
|
-
const agentMetadataStore = this.services.getAgentMetadataStore();
|
|
155
|
-
const userAgentsStore = this.services.getUserAgentsStore();
|
|
156
|
-
if (agentMetadataStore) {
|
|
157
|
-
const existing = await agentMetadataStore.getMetadata(agentId);
|
|
158
|
-
if (!existing) {
|
|
159
|
-
const agentName = isGroup
|
|
160
|
-
? `${platform} Group ${channelId}`
|
|
161
|
-
: `${platform} ${message.author?.fullName || userId}`;
|
|
162
|
-
await agentMetadataStore.createAgent(
|
|
163
|
-
agentId,
|
|
164
|
-
agentName,
|
|
165
|
-
platform,
|
|
166
|
-
userId,
|
|
167
|
-
{ parentConnectionId: this.connection.id }
|
|
168
|
-
);
|
|
169
|
-
await userAgentsStore?.addAgent(platform, userId, agentId);
|
|
170
|
-
logger.info({ agentId, userId }, "Auto-created agent");
|
|
171
|
-
|
|
172
|
-
// Clone settings from template agent if connection has one
|
|
173
|
-
if (this.connection.templateAgentId) {
|
|
174
|
-
try {
|
|
175
|
-
const agentSettingsStore = this.services.getAgentSettingsStore();
|
|
176
|
-
if (agentSettingsStore) {
|
|
177
|
-
const templateSettings = await agentSettingsStore.getSettings(
|
|
178
|
-
this.connection.templateAgentId
|
|
179
|
-
);
|
|
180
|
-
if (templateSettings) {
|
|
181
|
-
const { buildDefaultSettingsFromSource } = await import(
|
|
182
|
-
"../auth/settings/template-utils"
|
|
183
|
-
);
|
|
184
|
-
const cloned = buildDefaultSettingsFromSource(templateSettings);
|
|
185
|
-
cloned.templateAgentId = this.connection.templateAgentId;
|
|
186
|
-
await agentSettingsStore.saveSettings(agentId, cloned);
|
|
187
|
-
logger.info(
|
|
188
|
-
{
|
|
189
|
-
agentId,
|
|
190
|
-
templateAgentId: this.connection.templateAgentId,
|
|
191
|
-
},
|
|
192
|
-
"Cloned settings from template agent"
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
} catch (error) {
|
|
197
|
-
logger.warn(
|
|
198
|
-
{
|
|
199
|
-
agentId,
|
|
200
|
-
templateAgentId: this.connection.templateAgentId,
|
|
201
|
-
error: String(error),
|
|
202
|
-
},
|
|
203
|
-
"Failed to clone template agent settings"
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Gap 7: Audio transcription
|
|
211
|
-
let messageText = message.text ?? "";
|
|
212
|
-
const transcriptionService = this.services.getTranscriptionService();
|
|
213
|
-
if (transcriptionService && message.attachments?.length) {
|
|
214
|
-
for (const attachment of message.attachments) {
|
|
215
|
-
const mime = attachment.mimeType ?? "";
|
|
216
|
-
if (
|
|
217
|
-
mime.startsWith("audio/") ||
|
|
218
|
-
mime === "application/ogg" ||
|
|
219
|
-
mime.startsWith("video/note")
|
|
220
|
-
) {
|
|
221
|
-
try {
|
|
222
|
-
const data = await attachment.fetchData?.();
|
|
223
|
-
if (data) {
|
|
224
|
-
const result = await transcriptionService.transcribe(
|
|
225
|
-
Buffer.from(data),
|
|
226
|
-
agentId,
|
|
227
|
-
mime
|
|
228
|
-
);
|
|
229
|
-
if ("text" in result && result.text) {
|
|
230
|
-
messageText = messageText
|
|
231
|
-
? `${messageText}\n\n[Voice message]: ${result.text}`
|
|
232
|
-
: result.text;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
} catch (error) {
|
|
236
|
-
logger.warn(
|
|
237
|
-
{ error: String(error), messageId },
|
|
238
|
-
"Audio transcription failed"
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Remove bot mention from text
|
|
246
|
-
const botUsername = this.manager.getInstance(this.connection.id)?.connection
|
|
247
|
-
.metadata.botUsername;
|
|
248
|
-
if (botUsername) {
|
|
249
|
-
messageText = messageText.replace(`@${botUsername}`, "").trim();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// Intercept /new and /clear before slash dispatch
|
|
253
|
-
let sessionReset = false;
|
|
254
|
-
const trimmedLower = messageText.trim().toLowerCase();
|
|
255
|
-
if (trimmedLower === "/new") {
|
|
256
|
-
messageText = "Starting new session.";
|
|
257
|
-
sessionReset = true;
|
|
258
|
-
} else if (trimmedLower === "/clear") {
|
|
259
|
-
const historyKey = `chat:history:${this.connection.id}:${channelId}`;
|
|
260
|
-
await this.redis.del(historyKey);
|
|
261
|
-
await thread.post({ text: "Chat history cleared." });
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// Slash command dispatch — intercept before queueing to worker
|
|
266
|
-
if (!sessionReset && this.commandDispatcher) {
|
|
267
|
-
const handled = await this.commandDispatcher.tryHandleSlashText(
|
|
268
|
-
messageText,
|
|
269
|
-
{
|
|
270
|
-
platform,
|
|
271
|
-
userId,
|
|
272
|
-
channelId,
|
|
273
|
-
isGroup,
|
|
274
|
-
conversationId: messageId,
|
|
275
|
-
connectionId: this.connection.id,
|
|
276
|
-
reply: createChatReply((content) => thread.post(content)),
|
|
277
|
-
}
|
|
278
|
-
);
|
|
279
|
-
if (handled) return;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Gap 1: Retrieve conversation history from Redis
|
|
283
|
-
const historyKey = `chat:history:${this.connection.id}:${channelId}`;
|
|
284
|
-
const conversationHistory = await this.getHistory(historyKey);
|
|
285
|
-
|
|
286
|
-
// Gap 1: Store inbound message
|
|
287
|
-
await this.appendHistory(historyKey, {
|
|
288
|
-
role: "user",
|
|
289
|
-
content: messageText,
|
|
290
|
-
authorName: message.author?.fullName,
|
|
291
|
-
timestamp: Date.now(),
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
// Build payload and enqueue
|
|
295
|
-
const traceId = generateTraceId(messageId);
|
|
296
|
-
const agentSettingsStore = this.services.getAgentSettingsStore();
|
|
297
|
-
|
|
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
|
-
});
|
|
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
|
-
}
|
|
314
|
-
|
|
315
|
-
const agentOptions = await resolveAgentOptions(
|
|
316
|
-
agentId,
|
|
317
|
-
{},
|
|
318
|
-
agentSettingsStore
|
|
319
|
-
);
|
|
320
|
-
|
|
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);
|
|
353
|
-
|
|
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
|
-
);
|
|
364
|
-
|
|
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();
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Gap 1: Redis-backed conversation history
|
|
378
|
-
|
|
379
|
-
private async getHistory(
|
|
380
|
-
key: string
|
|
381
|
-
): Promise<
|
|
382
|
-
Array<{ role: "user" | "assistant"; content: string; name?: string }>
|
|
383
|
-
> {
|
|
384
|
-
const raw = await this.redis.lrange(key, 0, MAX_HISTORY_MESSAGES - 1);
|
|
385
|
-
const results: Array<{
|
|
386
|
-
role: "user" | "assistant";
|
|
387
|
-
content: string;
|
|
388
|
-
name?: string;
|
|
389
|
-
}> = [];
|
|
390
|
-
for (const entry of raw) {
|
|
391
|
-
try {
|
|
392
|
-
const parsed = JSON.parse(entry) as HistoryEntry;
|
|
393
|
-
results.push({
|
|
394
|
-
role: parsed.role,
|
|
395
|
-
content: parsed.content,
|
|
396
|
-
name: parsed.authorName,
|
|
397
|
-
});
|
|
398
|
-
} catch (err) {
|
|
399
|
-
logger.warn(
|
|
400
|
-
{ key, error: String(err) },
|
|
401
|
-
"Skipping corrupt history entry"
|
|
402
|
-
);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
return results;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
private async appendHistory(key: string, entry: HistoryEntry): Promise<void> {
|
|
409
|
-
await this.redis
|
|
410
|
-
.pipeline()
|
|
411
|
-
.rpush(key, JSON.stringify(entry))
|
|
412
|
-
.ltrim(key, -MAX_HISTORY_MESSAGES, -1)
|
|
413
|
-
.expire(key, HISTORY_TTL_SECONDS)
|
|
414
|
-
.exec();
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
* Store an outgoing bot response in conversation history.
|
|
420
|
-
* Called from the response bridge.
|
|
421
|
-
*/
|
|
422
|
-
export async function storeOutgoingHistory(
|
|
423
|
-
redis: Redis,
|
|
424
|
-
connectionId: string,
|
|
425
|
-
channelId: string,
|
|
426
|
-
text: string
|
|
427
|
-
): Promise<void> {
|
|
428
|
-
const key = `chat:history:${connectionId}:${channelId}`;
|
|
429
|
-
const entry: HistoryEntry = {
|
|
430
|
-
role: "assistant",
|
|
431
|
-
content: text,
|
|
432
|
-
timestamp: Date.now(),
|
|
433
|
-
};
|
|
434
|
-
await redis
|
|
435
|
-
.pipeline()
|
|
436
|
-
.rpush(key, JSON.stringify(entry))
|
|
437
|
-
.ltrim(key, -MAX_HISTORY_MESSAGES, -1)
|
|
438
|
-
.expire(key, HISTORY_TTL_SECONDS)
|
|
439
|
-
.exec();
|
|
440
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export interface PlatformAuthMethod {
|
|
2
|
-
type: "oauth" | "claim-code";
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
const DEFAULT_AUTH_METHOD: PlatformAuthMethod = { type: "claim-code" };
|
|
6
|
-
|
|
7
|
-
const AUTH_METHODS: Record<string, PlatformAuthMethod> = {
|
|
8
|
-
telegram: {
|
|
9
|
-
type: "claim-code",
|
|
10
|
-
},
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export function getAuthMethod(platform: string): PlatformAuthMethod {
|
|
14
|
-
return AUTH_METHODS[platform] || DEFAULT_AUTH_METHOD;
|
|
15
|
-
}
|
package/src/connections/types.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Platform connection types for API-driven Chat SDK integrations.
|
|
3
|
-
* Config types are derived directly from adapter factory signatures — zero maintenance.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { createDiscordAdapter } from "@chat-adapter/discord";
|
|
7
|
-
import type { createGoogleChatAdapter } from "@chat-adapter/gchat";
|
|
8
|
-
import type { createSlackAdapter } from "@chat-adapter/slack";
|
|
9
|
-
import type { createTeamsAdapter } from "@chat-adapter/teams";
|
|
10
|
-
import type { createTelegramAdapter } from "@chat-adapter/telegram";
|
|
11
|
-
import type { createWhatsAppAdapter } from "@chat-adapter/whatsapp";
|
|
12
|
-
|
|
13
|
-
// Derive config types from what the adapter factories actually accept
|
|
14
|
-
type TelegramAdapterConfig = NonNullable<
|
|
15
|
-
Parameters<typeof createTelegramAdapter>[0]
|
|
16
|
-
> & { platform: "telegram" };
|
|
17
|
-
type SlackAdapterConfig = NonNullable<
|
|
18
|
-
Parameters<typeof createSlackAdapter>[0]
|
|
19
|
-
> & { platform: "slack" };
|
|
20
|
-
type DiscordAdapterConfig = NonNullable<
|
|
21
|
-
Parameters<typeof createDiscordAdapter>[0]
|
|
22
|
-
> & { platform: "discord" };
|
|
23
|
-
type WhatsAppAdapterConfig = NonNullable<
|
|
24
|
-
Parameters<typeof createWhatsAppAdapter>[0]
|
|
25
|
-
> & { platform: "whatsapp" };
|
|
26
|
-
type TeamsAdapterConfig = NonNullable<
|
|
27
|
-
Parameters<typeof createTeamsAdapter>[0]
|
|
28
|
-
> & { platform: "teams" };
|
|
29
|
-
type GoogleChatAdapterConfig = NonNullable<
|
|
30
|
-
Parameters<typeof createGoogleChatAdapter>[0]
|
|
31
|
-
> & { platform: "gchat" };
|
|
32
|
-
|
|
33
|
-
export type PlatformAdapterConfig =
|
|
34
|
-
| TelegramAdapterConfig
|
|
35
|
-
| SlackAdapterConfig
|
|
36
|
-
| DiscordAdapterConfig
|
|
37
|
-
| WhatsAppAdapterConfig
|
|
38
|
-
| TeamsAdapterConfig
|
|
39
|
-
| GoogleChatAdapterConfig;
|
|
40
|
-
|
|
41
|
-
export interface PlatformConnection {
|
|
42
|
-
id: string;
|
|
43
|
-
platform: string;
|
|
44
|
-
templateAgentId?: string;
|
|
45
|
-
config: PlatformAdapterConfig;
|
|
46
|
-
settings: ConnectionSettings;
|
|
47
|
-
metadata: Record<string, any>;
|
|
48
|
-
status: "active" | "stopped" | "error";
|
|
49
|
-
errorMessage?: string;
|
|
50
|
-
createdAt: number;
|
|
51
|
-
updatedAt: number;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export type UserConfigScope =
|
|
55
|
-
| "model"
|
|
56
|
-
| "view-model"
|
|
57
|
-
| "system-prompt"
|
|
58
|
-
| "skills"
|
|
59
|
-
| "schedules"
|
|
60
|
-
| "permissions"
|
|
61
|
-
| "packages";
|
|
62
|
-
|
|
63
|
-
export interface ConnectionSettings {
|
|
64
|
-
allowFrom?: string[];
|
|
65
|
-
allowGroups?: boolean;
|
|
66
|
-
userConfigScopes?: UserConfigScope[];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** Heuristic: field names matching these patterns contain secrets and must be encrypted at rest. */
|
|
70
|
-
const SECRET_FIELD_PATTERNS = [
|
|
71
|
-
"token",
|
|
72
|
-
"secret",
|
|
73
|
-
"password",
|
|
74
|
-
"key",
|
|
75
|
-
"credential",
|
|
76
|
-
];
|
|
77
|
-
|
|
78
|
-
export function isSecretField(fieldName: string): boolean {
|
|
79
|
-
const lower = fieldName.toLowerCase();
|
|
80
|
-
return SECRET_FIELD_PATTERNS.some((p) => lower.includes(p));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** Derived from PlatformAdapterConfig — no separate list to maintain. */
|
|
84
|
-
export type SupportedPlatform = PlatformAdapterConfig["platform"];
|