@lobu/gateway 3.0.9 → 3.0.12

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.
Files changed (210) hide show
  1. package/dist/api/platform.d.ts.map +1 -1
  2. package/dist/api/platform.js +7 -26
  3. package/dist/api/platform.js.map +1 -1
  4. package/dist/auth/mcp/proxy.d.ts +14 -0
  5. package/dist/auth/mcp/proxy.d.ts.map +1 -1
  6. package/dist/auth/mcp/proxy.js +149 -13
  7. package/dist/auth/mcp/proxy.js.map +1 -1
  8. package/dist/cli/gateway.d.ts.map +1 -1
  9. package/dist/cli/gateway.js +29 -0
  10. package/dist/cli/gateway.js.map +1 -1
  11. package/dist/connections/chat-instance-manager.d.ts.map +1 -1
  12. package/dist/connections/chat-instance-manager.js +2 -1
  13. package/dist/connections/chat-instance-manager.js.map +1 -1
  14. package/dist/connections/interaction-bridge.d.ts +9 -2
  15. package/dist/connections/interaction-bridge.d.ts.map +1 -1
  16. package/dist/connections/interaction-bridge.js +121 -261
  17. package/dist/connections/interaction-bridge.js.map +1 -1
  18. package/dist/interactions.d.ts +9 -43
  19. package/dist/interactions.d.ts.map +1 -1
  20. package/dist/interactions.js +10 -52
  21. package/dist/interactions.js.map +1 -1
  22. package/dist/routes/public/agent.d.ts +4 -0
  23. package/dist/routes/public/agent.d.ts.map +1 -1
  24. package/dist/routes/public/agent.js +21 -0
  25. package/dist/routes/public/agent.js.map +1 -1
  26. package/dist/services/core-services.d.ts.map +1 -1
  27. package/dist/services/core-services.js +4 -0
  28. package/dist/services/core-services.js.map +1 -1
  29. package/package.json +9 -9
  30. package/src/__tests__/agent-config-routes.test.ts +0 -254
  31. package/src/__tests__/agent-history-routes.test.ts +0 -72
  32. package/src/__tests__/agent-routes.test.ts +0 -68
  33. package/src/__tests__/agent-schedules-routes.test.ts +0 -59
  34. package/src/__tests__/agent-settings-store.test.ts +0 -323
  35. package/src/__tests__/bedrock-model-catalog.test.ts +0 -40
  36. package/src/__tests__/bedrock-openai-service.test.ts +0 -157
  37. package/src/__tests__/bedrock-provider-module.test.ts +0 -56
  38. package/src/__tests__/chat-instance-manager-slack.test.ts +0 -204
  39. package/src/__tests__/chat-response-bridge.test.ts +0 -131
  40. package/src/__tests__/config-memory-plugins.test.ts +0 -92
  41. package/src/__tests__/config-request-store.test.ts +0 -127
  42. package/src/__tests__/connection-routes.test.ts +0 -144
  43. package/src/__tests__/core-services-store-selection.test.ts +0 -92
  44. package/src/__tests__/docker-deployment.test.ts +0 -1211
  45. package/src/__tests__/embedded-deployment.test.ts +0 -342
  46. package/src/__tests__/grant-store.test.ts +0 -148
  47. package/src/__tests__/http-proxy.test.ts +0 -281
  48. package/src/__tests__/instruction-service.test.ts +0 -37
  49. package/src/__tests__/link-buttons.test.ts +0 -112
  50. package/src/__tests__/lobu.test.ts +0 -32
  51. package/src/__tests__/mcp-config-service.test.ts +0 -347
  52. package/src/__tests__/mcp-proxy.test.ts +0 -694
  53. package/src/__tests__/message-handler-bridge.test.ts +0 -17
  54. package/src/__tests__/model-selection.test.ts +0 -172
  55. package/src/__tests__/oauth-templates.test.ts +0 -39
  56. package/src/__tests__/platform-adapter-slack-send.test.ts +0 -114
  57. package/src/__tests__/platform-helpers-model-resolution.test.ts +0 -253
  58. package/src/__tests__/provider-inheritance.test.ts +0 -212
  59. package/src/__tests__/routes/cli-auth.test.ts +0 -337
  60. package/src/__tests__/routes/interactions.test.ts +0 -121
  61. package/src/__tests__/secret-proxy.test.ts +0 -85
  62. package/src/__tests__/session-manager.test.ts +0 -572
  63. package/src/__tests__/setup.ts +0 -133
  64. package/src/__tests__/skill-and-mcp-registry.test.ts +0 -203
  65. package/src/__tests__/slack-routes.test.ts +0 -161
  66. package/src/__tests__/system-config-resolver.test.ts +0 -75
  67. package/src/__tests__/system-message-limiter.test.ts +0 -89
  68. package/src/__tests__/system-skills-service.test.ts +0 -362
  69. package/src/__tests__/transcription-service.test.ts +0 -222
  70. package/src/__tests__/utils/rate-limiter.test.ts +0 -102
  71. package/src/__tests__/worker-connection-manager.test.ts +0 -497
  72. package/src/__tests__/worker-job-router.test.ts +0 -722
  73. package/src/api/index.ts +0 -1
  74. package/src/api/platform.ts +0 -292
  75. package/src/api/response-renderer.ts +0 -157
  76. package/src/auth/agent-metadata-store.ts +0 -168
  77. package/src/auth/api-auth-middleware.ts +0 -69
  78. package/src/auth/api-key-provider-module.ts +0 -213
  79. package/src/auth/base-provider-module.ts +0 -201
  80. package/src/auth/bedrock/provider-module.ts +0 -110
  81. package/src/auth/chatgpt/chatgpt-oauth-module.ts +0 -185
  82. package/src/auth/chatgpt/device-code-client.ts +0 -218
  83. package/src/auth/chatgpt/index.ts +0 -1
  84. package/src/auth/claude/oauth-module.ts +0 -280
  85. package/src/auth/cli/token-service.ts +0 -249
  86. package/src/auth/external/client.ts +0 -560
  87. package/src/auth/external/device-code-client.ts +0 -235
  88. package/src/auth/mcp/config-service.ts +0 -420
  89. package/src/auth/mcp/proxy.ts +0 -1086
  90. package/src/auth/mcp/string-substitution.ts +0 -17
  91. package/src/auth/mcp/tool-cache.ts +0 -90
  92. package/src/auth/oauth/base-client.ts +0 -267
  93. package/src/auth/oauth/client.ts +0 -153
  94. package/src/auth/oauth/credentials.ts +0 -7
  95. package/src/auth/oauth/providers.ts +0 -69
  96. package/src/auth/oauth/state-store.ts +0 -150
  97. package/src/auth/oauth-templates.ts +0 -179
  98. package/src/auth/provider-catalog.ts +0 -220
  99. package/src/auth/provider-model-options.ts +0 -41
  100. package/src/auth/settings/agent-settings-store.ts +0 -565
  101. package/src/auth/settings/auth-profiles-manager.ts +0 -216
  102. package/src/auth/settings/index.ts +0 -12
  103. package/src/auth/settings/model-preference-store.ts +0 -52
  104. package/src/auth/settings/model-selection.ts +0 -135
  105. package/src/auth/settings/resolved-settings-view.ts +0 -298
  106. package/src/auth/settings/template-utils.ts +0 -44
  107. package/src/auth/settings/token-service.ts +0 -88
  108. package/src/auth/system-env-store.ts +0 -98
  109. package/src/auth/user-agents-store.ts +0 -68
  110. package/src/channels/binding-service.ts +0 -214
  111. package/src/channels/index.ts +0 -4
  112. package/src/cli/gateway.ts +0 -1312
  113. package/src/cli/index.ts +0 -74
  114. package/src/commands/built-in-commands.ts +0 -80
  115. package/src/commands/command-dispatcher.ts +0 -94
  116. package/src/commands/command-reply-adapters.ts +0 -27
  117. package/src/config/file-loader.ts +0 -618
  118. package/src/config/index.ts +0 -588
  119. package/src/config/network-allowlist.ts +0 -71
  120. package/src/connections/chat-instance-manager.ts +0 -1284
  121. package/src/connections/chat-response-bridge.ts +0 -618
  122. package/src/connections/index.ts +0 -7
  123. package/src/connections/interaction-bridge.ts +0 -831
  124. package/src/connections/message-handler-bridge.ts +0 -440
  125. package/src/connections/platform-auth-methods.ts +0 -15
  126. package/src/connections/types.ts +0 -84
  127. package/src/gateway/connection-manager.ts +0 -291
  128. package/src/gateway/index.ts +0 -698
  129. package/src/gateway/job-router.ts +0 -201
  130. package/src/gateway-main.ts +0 -200
  131. package/src/index.ts +0 -41
  132. package/src/infrastructure/queue/index.ts +0 -12
  133. package/src/infrastructure/queue/queue-producer.ts +0 -148
  134. package/src/infrastructure/queue/redis-queue.ts +0 -361
  135. package/src/infrastructure/queue/types.ts +0 -133
  136. package/src/infrastructure/redis/system-message-limiter.ts +0 -94
  137. package/src/interactions/config-request-store.ts +0 -198
  138. package/src/interactions.ts +0 -363
  139. package/src/lobu.ts +0 -311
  140. package/src/metrics/prometheus.ts +0 -159
  141. package/src/modules/module-system.ts +0 -179
  142. package/src/orchestration/base-deployment-manager.ts +0 -900
  143. package/src/orchestration/deployment-utils.ts +0 -98
  144. package/src/orchestration/impl/docker-deployment.ts +0 -620
  145. package/src/orchestration/impl/embedded-deployment.ts +0 -268
  146. package/src/orchestration/impl/index.ts +0 -8
  147. package/src/orchestration/impl/k8s/deployment.ts +0 -1061
  148. package/src/orchestration/impl/k8s/helpers.ts +0 -610
  149. package/src/orchestration/impl/k8s/index.ts +0 -1
  150. package/src/orchestration/index.ts +0 -333
  151. package/src/orchestration/message-consumer.ts +0 -584
  152. package/src/orchestration/scheduled-wakeup.ts +0 -704
  153. package/src/permissions/approval-policy.ts +0 -36
  154. package/src/permissions/grant-store.ts +0 -219
  155. package/src/platform/file-handler.ts +0 -66
  156. package/src/platform/link-buttons.ts +0 -57
  157. package/src/platform/renderer-utils.ts +0 -44
  158. package/src/platform/response-renderer.ts +0 -84
  159. package/src/platform/unified-thread-consumer.ts +0 -194
  160. package/src/platform.ts +0 -318
  161. package/src/proxy/http-proxy.ts +0 -752
  162. package/src/proxy/proxy-manager.ts +0 -81
  163. package/src/proxy/secret-proxy.ts +0 -402
  164. package/src/proxy/token-refresh-job.ts +0 -143
  165. package/src/routes/internal/audio.ts +0 -141
  166. package/src/routes/internal/device-auth.ts +0 -652
  167. package/src/routes/internal/files.ts +0 -226
  168. package/src/routes/internal/history.ts +0 -69
  169. package/src/routes/internal/images.ts +0 -127
  170. package/src/routes/internal/interactions.ts +0 -84
  171. package/src/routes/internal/middleware.ts +0 -23
  172. package/src/routes/internal/schedule.ts +0 -226
  173. package/src/routes/internal/types.ts +0 -22
  174. package/src/routes/openapi-auto.ts +0 -239
  175. package/src/routes/public/agent-access.ts +0 -23
  176. package/src/routes/public/agent-config.ts +0 -675
  177. package/src/routes/public/agent-history.ts +0 -422
  178. package/src/routes/public/agent-schedules.ts +0 -296
  179. package/src/routes/public/agent.ts +0 -1086
  180. package/src/routes/public/agents.ts +0 -373
  181. package/src/routes/public/channels.ts +0 -191
  182. package/src/routes/public/cli-auth.ts +0 -896
  183. package/src/routes/public/connections.ts +0 -574
  184. package/src/routes/public/landing.ts +0 -16
  185. package/src/routes/public/oauth.ts +0 -147
  186. package/src/routes/public/settings-auth.ts +0 -104
  187. package/src/routes/public/slack.ts +0 -173
  188. package/src/routes/shared/agent-ownership.ts +0 -101
  189. package/src/routes/shared/token-verifier.ts +0 -34
  190. package/src/services/bedrock-model-catalog.ts +0 -217
  191. package/src/services/bedrock-openai-service.ts +0 -658
  192. package/src/services/core-services.ts +0 -1072
  193. package/src/services/image-generation-service.ts +0 -257
  194. package/src/services/instruction-service.ts +0 -318
  195. package/src/services/mcp-registry.ts +0 -94
  196. package/src/services/platform-helpers.ts +0 -287
  197. package/src/services/session-manager.ts +0 -262
  198. package/src/services/settings-resolver.ts +0 -74
  199. package/src/services/system-config-resolver.ts +0 -89
  200. package/src/services/system-skills-service.ts +0 -229
  201. package/src/services/transcription-service.ts +0 -684
  202. package/src/session.ts +0 -110
  203. package/src/spaces/index.ts +0 -1
  204. package/src/spaces/space-resolver.ts +0 -17
  205. package/src/stores/in-memory-agent-store.ts +0 -403
  206. package/src/stores/redis-agent-store.ts +0 -279
  207. package/src/utils/public-url.ts +0 -44
  208. package/src/utils/rate-limiter.ts +0 -94
  209. package/tsconfig.json +0 -33
  210. package/tsconfig.tsbuildinfo +0 -1
@@ -1,373 +0,0 @@
1
- /**
2
- * Agent Management Routes - Create, list, update, and delete user agents
3
- *
4
- * Routes:
5
- * - POST /api/v1/agents - Create a new agent
6
- * - GET /api/v1/agents - List user's agents (requires token)
7
- * - PATCH /api/v1/agents/{agentId} - Update agent name/description
8
- * - DELETE /api/v1/agents/{agentId} - Delete an agent
9
- */
10
-
11
- import { createLogger } from "@lobu/core";
12
- import { Hono } from "hono";
13
- import type { AgentMetadataStore } from "../../auth/agent-metadata-store";
14
- import type { AgentSettings, AgentSettingsStore } from "../../auth/settings";
15
- import { buildDefaultSettingsFromSource } from "../../auth/settings/template-utils";
16
- import type { SettingsTokenPayload } from "../../auth/settings/token-service";
17
- import type { UserAgentsStore } from "../../auth/user-agents-store";
18
- import type { ChannelBindingService } from "../../channels";
19
- import {
20
- resolveSettingsLookupUserId,
21
- verifyOwnedAgentAccess,
22
- } from "../shared/agent-ownership";
23
- import { verifySettingsSession } from "./settings-auth";
24
-
25
- const logger = createLogger("agent-routes");
26
-
27
- /** Environment-configurable limits */
28
- const MAX_AGENTS_PER_USER = parseInt(
29
- process.env.MAX_AGENTS_PER_USER || "0",
30
- 10
31
- );
32
-
33
- export interface AgentRoutesConfig {
34
- userAgentsStore: UserAgentsStore;
35
- agentMetadataStore: AgentMetadataStore;
36
- agentSettingsStore: AgentSettingsStore;
37
- channelBindingService: ChannelBindingService;
38
- }
39
-
40
- async function listOwnedAgentIds(
41
- payload: SettingsTokenPayload,
42
- config: Pick<AgentRoutesConfig, "userAgentsStore" | "agentMetadataStore">
43
- ): Promise<string[]> {
44
- const lookupUserId = resolveSettingsLookupUserId(payload);
45
- const agentIds = new Set(
46
- await config.userAgentsStore.listAgents(payload.platform, lookupUserId)
47
- );
48
-
49
- if (payload.platform === "external") {
50
- const allAgents = await config.agentMetadataStore.listAllAgents();
51
- for (const agent of allAgents) {
52
- if (agent.owner.userId === lookupUserId) {
53
- agentIds.add(agent.agentId);
54
- }
55
- }
56
- }
57
-
58
- return [...agentIds];
59
- }
60
-
61
- /**
62
- * Sanitize user-provided agentId.
63
- * Lowercase alphanumeric with hyphens, 3-60 chars, must start with a letter.
64
- */
65
- function sanitizeAgentId(input: string): string | null {
66
- const cleaned = input.toLowerCase().replace(/[^a-z0-9-]/g, "-");
67
- if (cleaned.length < 3 || cleaned.length > 60) return null;
68
- if (!/^[a-z]/.test(cleaned)) return null;
69
- return cleaned;
70
- }
71
-
72
- export function createAgentRoutes(config: AgentRoutesConfig): Hono {
73
- const router = new Hono();
74
-
75
- // POST /api/v1/agents - Create a new agent
76
- router.post("/", async (c) => {
77
- const payload = verifySettingsSession(c);
78
- if (!payload) {
79
- return c.json({ error: "Invalid or expired token" }, 401);
80
- }
81
-
82
- try {
83
- const lookupUserId = resolveSettingsLookupUserId(payload);
84
- const body = await c.req.json<{
85
- agentId: string;
86
- name: string;
87
- description?: string;
88
- channelId?: string;
89
- }>();
90
-
91
- if (!body.agentId || !body.name) {
92
- return c.json({ error: "agentId and name are required" }, 400);
93
- }
94
-
95
- const agentId = sanitizeAgentId(body.agentId);
96
- if (!agentId) {
97
- return c.json(
98
- {
99
- error:
100
- "Invalid agentId. Must be 3-40 chars, lowercase alphanumeric with hyphens, starting with a letter.",
101
- },
102
- 400
103
- );
104
- }
105
-
106
- // Check if agentId already exists
107
- const existing = await config.agentMetadataStore.hasAgent(agentId);
108
- if (existing) {
109
- return c.json({ error: "An agent with this ID already exists" }, 409);
110
- }
111
-
112
- // Check per-user limit (admins bypass)
113
- if (!payload.isAdmin && MAX_AGENTS_PER_USER > 0) {
114
- const userAgents = await listOwnedAgentIds(payload, config);
115
- if (userAgents.length >= MAX_AGENTS_PER_USER) {
116
- return c.json(
117
- {
118
- error: `Agent limit reached (${MAX_AGENTS_PER_USER}). Delete an existing agent first.`,
119
- },
120
- 429
121
- );
122
- }
123
- }
124
-
125
- // Create metadata
126
- await config.agentMetadataStore.createAgent(
127
- agentId,
128
- body.name,
129
- payload.platform,
130
- lookupUserId,
131
- { description: body.description }
132
- );
133
-
134
- // Create default settings, seeded from the current workspace/channel agent when available.
135
- let defaultSettings: Omit<AgentSettings, "updatedAt"> = {};
136
- try {
137
- let sourceAgentId = payload.agentId;
138
- if (!sourceAgentId && body.channelId) {
139
- const binding = await config.channelBindingService.getBinding(
140
- payload.platform,
141
- body.channelId,
142
- payload.teamId
143
- );
144
- sourceAgentId = binding?.agentId;
145
- }
146
-
147
- if (sourceAgentId) {
148
- const sourceSettings =
149
- await config.agentSettingsStore.getSettings(sourceAgentId);
150
- defaultSettings = buildDefaultSettingsFromSource(sourceSettings);
151
- }
152
- } catch (error) {
153
- logger.warn("Failed to derive source defaults for new agent", {
154
- error,
155
- });
156
- }
157
- await config.agentSettingsStore.saveSettings(agentId, defaultSettings);
158
-
159
- // Associate with user
160
- await config.userAgentsStore.addAgent(
161
- payload.platform,
162
- lookupUserId,
163
- agentId
164
- );
165
-
166
- // Auto-bind to channel if channelId provided (from session context)
167
- if (body.channelId) {
168
- await config.channelBindingService.createBinding(
169
- agentId,
170
- payload.platform,
171
- body.channelId,
172
- payload.teamId,
173
- { configuredBy: payload.userId }
174
- );
175
- }
176
-
177
- logger.info(
178
- `Created agent ${agentId} for user ${payload.platform}/${payload.userId}${body.channelId ? ` (bound to ${body.channelId})` : ""}`
179
- );
180
-
181
- return c.json({
182
- agentId,
183
- name: body.name,
184
- settingsUrl: `/api/v1/agents/${encodeURIComponent(agentId)}/config`,
185
- });
186
- } catch (error) {
187
- logger.error("Failed to create agent", { error });
188
- return c.json(
189
- {
190
- error: "Internal server error",
191
- },
192
- 500
193
- );
194
- }
195
- });
196
-
197
- // GET /api/v1/agents - List user's agents
198
- router.get("/", async (c) => {
199
- const payload = verifySettingsSession(c);
200
- if (!payload) {
201
- return c.json({ error: "Invalid or expired token" }, 401);
202
- }
203
-
204
- try {
205
- const agentIds = await listOwnedAgentIds(payload, config);
206
-
207
- const agents = [];
208
- for (const agentId of agentIds) {
209
- const metadata = await config.agentMetadataStore.getMetadata(agentId);
210
- if (metadata) {
211
- // Skip sandbox agents (auto-created under a connection)
212
- if (metadata.parentConnectionId) continue;
213
-
214
- const bindings =
215
- await config.channelBindingService.listBindings(agentId);
216
- agents.push({
217
- agentId,
218
- name: metadata.name,
219
- description: metadata.description,
220
- isWorkspaceAgent: metadata.isWorkspaceAgent,
221
- createdAt: metadata.createdAt,
222
- lastUsedAt: metadata.lastUsedAt,
223
- channelCount: bindings.length,
224
- });
225
- }
226
- }
227
-
228
- return c.json({ agents });
229
- } catch (error) {
230
- logger.error("Failed to list agents", { error });
231
- return c.json({ error: "Failed to list agents" }, 500);
232
- }
233
- });
234
-
235
- // PATCH /api/v1/agents/{agentId} - Update agent name/description
236
- router.patch("/:agentId", async (c) => {
237
- const payload = verifySettingsSession(c);
238
- if (!payload) {
239
- return c.json({ error: "Invalid or expired token" }, 401);
240
- }
241
-
242
- const agentId = c.req.param("agentId");
243
- if (!agentId) {
244
- return c.json({ error: "Missing agentId" }, 400);
245
- }
246
-
247
- try {
248
- // Verify ownership (admins bypass)
249
- if (!payload.isAdmin) {
250
- const access = await verifyOwnedAgentAccess(payload, agentId, {
251
- userAgentsStore: config.userAgentsStore,
252
- agentMetadataStore: config.agentMetadataStore,
253
- });
254
- if (!access.authorized) {
255
- return c.json({ error: "Agent not found or not owned by you" }, 404);
256
- }
257
- }
258
-
259
- const body = await c.req.json<{ name?: string; description?: string }>();
260
- const updates: { name?: string; description?: string } = {};
261
-
262
- if (body.name !== undefined) {
263
- const name = body.name.trim();
264
- if (!name || name.length > 100) {
265
- return c.json({ error: "Name must be 1-100 characters" }, 400);
266
- }
267
- updates.name = name;
268
- }
269
-
270
- if (body.description !== undefined) {
271
- const desc = body.description.trim();
272
- if (desc.length > 200) {
273
- return c.json(
274
- { error: "Description must be at most 200 characters" },
275
- 400
276
- );
277
- }
278
- updates.description = desc;
279
- }
280
-
281
- if (Object.keys(updates).length === 0) {
282
- return c.json({ error: "No fields to update" }, 400);
283
- }
284
-
285
- await config.agentMetadataStore.updateMetadata(agentId, updates);
286
- logger.info(`Updated agent identity for ${agentId}`);
287
- return c.json({ success: true });
288
- } catch (error) {
289
- logger.error("Failed to update agent", { error, agentId });
290
- return c.json(
291
- {
292
- error: "Internal server error",
293
- },
294
- 500
295
- );
296
- }
297
- });
298
-
299
- // DELETE /api/v1/agents/{agentId} - Delete an agent
300
- router.delete("/:agentId", async (c) => {
301
- const payload = verifySettingsSession(c);
302
- if (!payload) {
303
- return c.json({ error: "Invalid or expired token" }, 401);
304
- }
305
-
306
- const agentId = c.req.param("agentId");
307
- if (!agentId) {
308
- return c.json({ error: "Missing agentId" }, 400);
309
- }
310
-
311
- try {
312
- // Verify ownership (admins bypass)
313
- let ownerPlatform: string | undefined;
314
- let ownerUserId: string | undefined;
315
- if (!payload.isAdmin) {
316
- const access = await verifyOwnedAgentAccess(payload, agentId, {
317
- userAgentsStore: config.userAgentsStore,
318
- agentMetadataStore: config.agentMetadataStore,
319
- });
320
- if (!access.authorized) {
321
- return c.json({ error: "Agent not found or not owned by you" }, 404);
322
- }
323
- ownerPlatform = access.ownerPlatform;
324
- ownerUserId = access.ownerUserId;
325
- }
326
-
327
- // Auto-unbind all channels
328
- const unboundCount =
329
- await config.channelBindingService.deleteAllBindings(agentId);
330
-
331
- // Delete settings
332
- await config.agentSettingsStore.deleteSettings(agentId);
333
-
334
- // Delete metadata
335
- await config.agentMetadataStore.deleteAgent(agentId);
336
-
337
- // Remove from user's list
338
- await config.userAgentsStore.removeAgent(
339
- payload.platform,
340
- resolveSettingsLookupUserId(payload),
341
- agentId
342
- );
343
- if (
344
- ownerPlatform &&
345
- ownerUserId &&
346
- (ownerPlatform !== payload.platform || ownerUserId !== payload.userId)
347
- ) {
348
- await config.userAgentsStore.removeAgent(
349
- ownerPlatform,
350
- ownerUserId,
351
- agentId
352
- );
353
- }
354
-
355
- logger.info(
356
- `Deleted agent ${agentId} (unbound ${unboundCount} channels)`
357
- );
358
-
359
- return c.json({ success: true, unboundChannels: unboundCount });
360
- } catch (error) {
361
- logger.error("Failed to delete agent", { error, agentId });
362
- return c.json(
363
- {
364
- error: "Internal server error",
365
- },
366
- 500
367
- );
368
- }
369
- });
370
-
371
- logger.debug("Agent management routes registered");
372
- return router;
373
- }
@@ -1,191 +0,0 @@
1
- /**
2
- * Channel Binding Routes - Manage channel-to-agent bindings
3
- *
4
- * Routes (under /api/v1/agents/{agentId}/channels):
5
- * - GET / - List all bindings for an agent
6
- * - POST / - Create a new binding
7
- * - DELETE /{platform}/{channelId} - Delete a binding
8
- */
9
-
10
- import { createLogger } from "@lobu/core";
11
- import { Hono } from "hono";
12
- import type { AgentMetadataStore } from "../../auth/agent-metadata-store";
13
- import type { UserAgentsStore } from "../../auth/user-agents-store";
14
- import type { ChannelBindingService } from "../../channels";
15
- import { createTokenVerifier } from "../shared/token-verifier";
16
- import { verifySettingsSession } from "./settings-auth";
17
-
18
- const logger = createLogger("channel-binding-routes");
19
-
20
- export interface ChannelBindingRoutesConfig {
21
- channelBindingService: ChannelBindingService;
22
- userAgentsStore?: UserAgentsStore;
23
- agentMetadataStore?: AgentMetadataStore;
24
- }
25
-
26
- /**
27
- * Create channel binding routes
28
- * These are mounted under /api/v1/agents/{agentId}/channels
29
- */
30
- export function createChannelBindingRoutes(
31
- config: ChannelBindingRoutesConfig
32
- ): Hono {
33
- const router = new Hono();
34
-
35
- const verifyToken = createTokenVerifier(config);
36
-
37
- const verifyAuth = async (c: any, agentId: string) => {
38
- return verifyToken(verifySettingsSession(c), agentId);
39
- };
40
-
41
- // GET /api/v1/agents/{agentId}/channels - List all bindings for an agent
42
- router.get("/", async (c) => {
43
- const agentId = c.req.param("agentId");
44
-
45
- if (!agentId) {
46
- return c.json({ error: "Missing agentId" }, 400);
47
- }
48
-
49
- if (!(await verifyAuth(c, agentId))) {
50
- return c.json({ error: "Unauthorized" }, 401);
51
- }
52
-
53
- try {
54
- const bindings = await config.channelBindingService.listBindings(agentId);
55
-
56
- return c.json({
57
- agentId,
58
- bindings: bindings.map((b) => ({
59
- platform: b.platform,
60
- channelId: b.channelId,
61
- teamId: b.teamId,
62
- createdAt: b.createdAt,
63
- })),
64
- });
65
- } catch (error) {
66
- logger.error("Failed to list bindings", { error, agentId });
67
- return c.json({ error: "Failed to list bindings" }, 500);
68
- }
69
- });
70
-
71
- // POST /api/v1/agents/{agentId}/channels - Create a new binding
72
- router.post("/", async (c) => {
73
- const agentId = c.req.param("agentId");
74
-
75
- if (!agentId) {
76
- return c.json({ error: "Missing agentId" }, 400);
77
- }
78
-
79
- const authPayload = await verifyAuth(c, agentId);
80
- if (!authPayload) {
81
- return c.json({ error: "Unauthorized" }, 401);
82
- }
83
-
84
- try {
85
- const body = await c.req.json<{
86
- platform: string;
87
- channelId: string;
88
- teamId?: string;
89
- }>();
90
-
91
- // Validate required fields
92
- if (!body.platform || !body.channelId) {
93
- return c.json(
94
- { error: "Missing required fields: platform, channelId" },
95
- 400
96
- );
97
- }
98
-
99
- // Validate platform format (alphanumeric, lowercase)
100
- if (!/^[a-z][a-z0-9_-]*$/.test(body.platform)) {
101
- return c.json(
102
- { error: "Invalid platform format. Must be lowercase alphanumeric." },
103
- 400
104
- );
105
- }
106
-
107
- // Validate channelId format
108
- if (typeof body.channelId !== "string" || !body.channelId.trim()) {
109
- return c.json({ error: "Invalid channelId" }, 400);
110
- }
111
-
112
- // Validate optional teamId
113
- if (
114
- body.teamId &&
115
- (typeof body.teamId !== "string" || !body.teamId.trim())
116
- ) {
117
- return c.json({ error: "Invalid teamId" }, 400);
118
- }
119
-
120
- await config.channelBindingService.createBinding(
121
- agentId,
122
- body.platform,
123
- body.channelId.trim(),
124
- body.teamId?.trim(),
125
- { configuredBy: authPayload.userId }
126
- );
127
-
128
- logger.info(
129
- `Created binding: ${body.platform}/${body.channelId} -> ${agentId}`
130
- );
131
-
132
- return c.json({
133
- success: true,
134
- agentId,
135
- platform: body.platform,
136
- channelId: body.channelId,
137
- teamId: body.teamId,
138
- });
139
- } catch (error) {
140
- logger.error("Failed to create binding", { error, agentId });
141
- return c.json(
142
- {
143
- error: "Failed to create binding",
144
- },
145
- 400
146
- );
147
- }
148
- });
149
-
150
- // DELETE /api/v1/agents/{agentId}/channels/{platform}/{channelId} - Delete a binding
151
- router.delete("/:platform/:channelId", async (c) => {
152
- const agentId = c.req.param("agentId");
153
- const platform = c.req.param("platform");
154
- const channelId = c.req.param("channelId");
155
- const teamId = c.req.query("teamId"); // Optional query param for multi-tenant platforms
156
-
157
- if (!agentId || !platform || !channelId) {
158
- return c.json({ error: "Missing required parameters" }, 400);
159
- }
160
-
161
- if (!(await verifyAuth(c, agentId))) {
162
- return c.json({ error: "Unauthorized" }, 401);
163
- }
164
-
165
- // Validate platform format
166
- if (!/^[a-z][a-z0-9_-]*$/.test(platform)) {
167
- return c.json({ error: "Invalid platform format" }, 400);
168
- }
169
-
170
- try {
171
- const deleted = await config.channelBindingService.deleteBinding(
172
- agentId,
173
- platform,
174
- channelId,
175
- teamId || undefined
176
- );
177
-
178
- if (!deleted) {
179
- return c.json({ error: "Binding not found" }, 404);
180
- }
181
-
182
- logger.info(`Deleted binding: ${platform}/${channelId} -> ${agentId}`);
183
- return c.json({ success: true });
184
- } catch (error) {
185
- logger.error("Failed to delete binding", { error, agentId });
186
- return c.json({ error: "Failed to delete binding" }, 500);
187
- }
188
- });
189
-
190
- return router;
191
- }