@axiom-lattice/gateway 3.0.2 → 3.0.3

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 (155) hide show
  1. package/dist/index.js +31 -9
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +31 -9
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +9 -6
  6. package/.eslintrc.json +0 -22
  7. package/.turbo/turbo-build.log +0 -46
  8. package/AGENTS.md +0 -112
  9. package/CHANGELOG.md +0 -1190
  10. package/LOGGER_CONFIG.md +0 -135
  11. package/RESUME_STREAM_CONTENT_BASED.md +0 -326
  12. package/RESUME_STREAM_README.md +0 -388
  13. package/jest.config.js +0 -72
  14. package/public/sdk/README.md +0 -695
  15. package/public/sdk/dashboard-engine-skill.md +0 -1122
  16. package/public/sdk/dashboard-single-file-spec.md +0 -357
  17. package/public/sdk/data-query-sdk-skill.md +0 -307
  18. package/public/sdk/data-query-sdk.d.ts +0 -252
  19. package/public/sdk/data-query-sdk.js +0 -970
  20. package/public/sdk/occupancy-dashboard.html +0 -363
  21. package/public/sdk/test-dashboard.html +0 -690
  22. package/scripts/seed-lark-installation.ts +0 -54
  23. package/src/__tests__/__mocks__/e2b.ts +0 -1
  24. package/src/__tests__/a2a.test.ts +0 -428
  25. package/src/__tests__/channel-installations.test.ts +0 -199
  26. package/src/__tests__/data-query.test.ts +0 -77
  27. package/src/__tests__/sandbox-provider-registration.test.ts +0 -74
  28. package/src/__tests__/setup.ts +0 -5
  29. package/src/__tests__/workspace.test.ts +0 -400
  30. package/src/channels/__tests__/routes.test.ts +0 -50
  31. package/src/channels/lark/LarkChannelAdapter.ts +0 -217
  32. package/src/channels/lark/README.md +0 -187
  33. package/src/channels/lark/__tests__/controller.test.ts +0 -136
  34. package/src/channels/lark/__tests__/mapping-service.test.ts +0 -118
  35. package/src/channels/lark/__tests__/parser.test.ts +0 -72
  36. package/src/channels/lark/__tests__/sender.test.ts +0 -37
  37. package/src/channels/lark/__tests__/verification.test.ts +0 -157
  38. package/src/channels/lark/controller.ts +0 -48
  39. package/src/channels/lark/mapping-service.ts +0 -138
  40. package/src/channels/lark/parser.ts +0 -68
  41. package/src/channels/lark/routes.ts +0 -22
  42. package/src/channels/lark/sender.ts +0 -58
  43. package/src/channels/lark/types.ts +0 -20
  44. package/src/channels/lark/verification.ts +0 -32
  45. package/src/channels/registry.ts +0 -20
  46. package/src/channels/routes.ts +0 -30
  47. package/src/channels/wechat/WechatChannelAdapter.ts +0 -294
  48. package/src/channels/wechat/__tests__/context-store.test.ts +0 -148
  49. package/src/channels/wechat/context-store.ts +0 -54
  50. package/src/channels/wechat/controller.ts +0 -59
  51. package/src/channels/wechat/routes.ts +0 -7
  52. package/src/channels/wechat/types.ts +0 -62
  53. package/src/channels/wechat/wechat-client.ts +0 -162
  54. package/src/config/local-a2a-templates.ts +0 -59
  55. package/src/config.ts +0 -124
  56. package/src/controllers/__tests__/assistant-local-a2a.test.ts +0 -147
  57. package/src/controllers/__tests__/local-a2a-templates.test.ts +0 -112
  58. package/src/controllers/__tests__/mime.test.ts +0 -74
  59. package/src/controllers/__tests__/resources.test.ts +0 -122
  60. package/src/controllers/__tests__/run.test.ts +0 -115
  61. package/src/controllers/__tests__/tasks.test.ts +0 -215
  62. package/src/controllers/__tests__/workflow-tracking.test.ts +0 -113
  63. package/src/controllers/agent_task.ts +0 -72
  64. package/src/controllers/assistant.ts +0 -490
  65. package/src/controllers/auth.ts +0 -524
  66. package/src/controllers/channel-bindings.ts +0 -135
  67. package/src/controllers/channel-installations.ts +0 -409
  68. package/src/controllers/collections.ts +0 -176
  69. package/src/controllers/config.ts +0 -126
  70. package/src/controllers/connections.ts +0 -181
  71. package/src/controllers/data-query.ts +0 -236
  72. package/src/controllers/database-configs.ts +0 -440
  73. package/src/controllers/embeddings.ts +0 -22
  74. package/src/controllers/entries.ts +0 -167
  75. package/src/controllers/eval.ts +0 -513
  76. package/src/controllers/export-import.ts +0 -166
  77. package/src/controllers/health.ts +0 -36
  78. package/src/controllers/local-a2a-templates.ts +0 -18
  79. package/src/controllers/local-a2a.ts +0 -149
  80. package/src/controllers/mcp-configs.ts +0 -673
  81. package/src/controllers/memory.ts +0 -257
  82. package/src/controllers/menu-items.ts +0 -114
  83. package/src/controllers/metrics-configs.ts +0 -1061
  84. package/src/controllers/middleware-types.ts +0 -15
  85. package/src/controllers/models.ts +0 -199
  86. package/src/controllers/personal-assistant.ts +0 -191
  87. package/src/controllers/resources.ts +0 -477
  88. package/src/controllers/run.ts +0 -338
  89. package/src/controllers/sandbox.ts +0 -255
  90. package/src/controllers/schedules.ts +0 -336
  91. package/src/controllers/skills.ts +0 -256
  92. package/src/controllers/tasks.ts +0 -213
  93. package/src/controllers/tenants.ts +0 -121
  94. package/src/controllers/thread_status.ts +0 -66
  95. package/src/controllers/threads.ts +0 -260
  96. package/src/controllers/tools.ts +0 -139
  97. package/src/controllers/users.ts +0 -135
  98. package/src/controllers/workflow-tracking.ts +0 -693
  99. package/src/controllers/workspace.ts +0 -879
  100. package/src/export_registrations/a2a-api-key.registration.ts +0 -89
  101. package/src/export_registrations/agent.registration.ts +0 -80
  102. package/src/export_registrations/binding.registration.ts +0 -106
  103. package/src/export_registrations/channel-installation.registration.ts +0 -88
  104. package/src/export_registrations/collection.registration.ts +0 -85
  105. package/src/export_registrations/connection.registration.ts +0 -97
  106. package/src/export_registrations/database-config.registration.ts +0 -94
  107. package/src/export_registrations/eval.registration.ts +0 -334
  108. package/src/export_registrations/index.ts +0 -31
  109. package/src/export_registrations/mcp-config.registration.ts +0 -97
  110. package/src/export_registrations/menu.registration.ts +0 -91
  111. package/src/export_registrations/metrics-config.registration.ts +0 -94
  112. package/src/export_registrations/skill.registration.ts +0 -88
  113. package/src/export_registrations/task.registration.ts +0 -99
  114. package/src/index.ts +0 -497
  115. package/src/logger/Logger.ts +0 -186
  116. package/src/router/MessageContext.ts +0 -14
  117. package/src/router/MessageRouter.ts +0 -490
  118. package/src/router/middlewares/auditLogger.ts +0 -34
  119. package/src/router/middlewares/deduplication.ts +0 -38
  120. package/src/router/middlewares/index.ts +0 -3
  121. package/src/router/middlewares/rateLimit.ts +0 -46
  122. package/src/routes/__tests__/a2a-test-connection.test.ts +0 -177
  123. package/src/routes/a2a-bridge.ts +0 -266
  124. package/src/routes/a2a-test-connection.ts +0 -126
  125. package/src/routes/a2a.ts +0 -851
  126. package/src/routes/channel-bindings.ts +0 -11
  127. package/src/routes/channel-installations.ts +0 -33
  128. package/src/routes/index.ts +0 -640
  129. package/src/routes/menu-items.ts +0 -10
  130. package/src/routes/resource-routes.ts +0 -35
  131. package/src/routes/stt.ts +0 -102
  132. package/src/schemas/data-query.ts +0 -69
  133. package/src/schemas/index.ts +0 -852
  134. package/src/services/ExportImportService.ts +0 -296
  135. package/src/services/__tests__/ExportImportService.test.ts +0 -130
  136. package/src/services/__tests__/eval-runner.test.ts +0 -131
  137. package/src/services/__tests__/local-a2a.test.ts +0 -124
  138. package/src/services/agent_task_consumer.ts +0 -348
  139. package/src/services/collection_service.ts +0 -258
  140. package/src/services/eval-runner.ts +0 -283
  141. package/src/services/local-a2a.ts +0 -354
  142. package/src/services/queue_service.ts +0 -104
  143. package/src/services/sandbox_service.ts +0 -223
  144. package/src/services/skill_service.ts +0 -97
  145. package/src/services/supabase.ts +0 -60
  146. package/src/swagger.ts +0 -77
  147. package/src/types/index.ts +0 -118
  148. package/src/types/koa.d.ts +0 -7
  149. package/src/utils/__tests__/local-a2a-runtime.test.ts +0 -77
  150. package/src/utils/__tests__/path-containment.test.ts +0 -35
  151. package/src/utils/a2a-url.ts +0 -20
  152. package/src/utils/local-a2a-runtime.ts +0 -107
  153. package/src/utils/mime.ts +0 -44
  154. package/src/utils/path-containment.ts +0 -38
  155. package/tsconfig.json +0 -26
@@ -1,490 +0,0 @@
1
- import { FastifyRequest, FastifyReply } from "fastify";
2
- import { agentInstanceManager, getStoreLattice } from "@axiom-lattice/core";
3
- import type {
4
- Assistant,
5
- CreateAssistantRequest,
6
- } from "@axiom-lattice/protocols";
7
- import { AgentType } from "@axiom-lattice/protocols";
8
- import type { A2ARemoteAgentConfig } from "@axiom-lattice/protocols";
9
- import { randomUUID } from "crypto";
10
- import type { AgentConfig } from "@axiom-lattice/core";
11
- import { agentLatticeManager, eventBus } from "@axiom-lattice/core";
12
- import { localA2AService } from "../services/local-a2a";
13
- import { normalizeA2AAgentCardUrl } from "../utils/a2a-url";
14
- import {
15
- getAgentCardPort,
16
- validateLocalRuntimeCommand,
17
- validateLocalRuntimePort,
18
- } from "../utils/local-a2a-runtime";
19
-
20
- /**
21
- * Assistant Controller
22
- * Handles assistant-related CRUD operations
23
- * Merges code-configured agents (from @axiom-lattice/core) with in-memory stored assistants
24
- * GET operations return both code-configured and stored assistants
25
- * CUD operations only work on stored assistants
26
- */
27
-
28
- /**
29
- * Get tenant ID from authenticated user context
30
- * Falls back to request headers for backward compatibility
31
- */
32
- function getTenantId(request: FastifyRequest): string {
33
- // First try to get from authenticated user context
34
- const userTenantId = (request as any).user?.tenantId;
35
- if (userTenantId) {
36
- return userTenantId;
37
- }
38
-
39
- // Fallback to request headers for backward compatibility
40
- return (request.headers["x-tenant-id"] as string) || "default";
41
- }
42
-
43
- function getUserId(request: FastifyRequest): string | undefined {
44
- const userId = (request as any).user?.id;
45
- if (userId) return userId;
46
- return (request.headers["x-user-id"] as string) || undefined;
47
- }
48
-
49
- /**
50
- * Convert AgentConfig to Assistant format
51
- */
52
- function convertAgentConfigToAssistant(config: AgentConfig): Assistant {
53
- return {
54
- id: config.key,
55
- tenantId: "default", // Code-configured agents belong to default tenant
56
- name: config.name,
57
- description: config.description,
58
- graphDefinition: config, // Store the full config as graphDefinition
59
- createdAt: new Date(0), // Code-configured agents have no creation date
60
- updatedAt: new Date(0), // Code-configured agents have no update date
61
- };
62
- }
63
-
64
- /**
65
- * Assistant list response interface
66
- */
67
- interface AssistantListResponse {
68
- success: boolean;
69
- message: string;
70
- data: {
71
- records: Assistant[];
72
- total: number;
73
- };
74
- }
75
-
76
- /**
77
- * Assistant response interface
78
- */
79
- interface AssistantResponse {
80
- success: boolean;
81
- message: string;
82
- data?: Assistant;
83
- }
84
-
85
- /**
86
- * Assistant update request body interface
87
- */
88
- interface AssistantUpdateBody {
89
- name?: string;
90
- description?: string;
91
- graphDefinition?: any;
92
- }
93
-
94
- /**
95
- * Get list of all assistants
96
- * Merges code-configured agents with stored assistants
97
- */
98
- export async function getAssistantList(
99
- request: FastifyRequest,
100
- reply: FastifyReply
101
- ): Promise<AssistantListResponse> {
102
- const tenantId = getTenantId(request);
103
-
104
- // Get code-configured agents for the tenant
105
- const agentConfigs = await agentLatticeManager.getAllAgentConfigsByTenant(tenantId);
106
- const codeConfiguredAssistants = agentConfigs.map(
107
- convertAgentConfigToAssistant
108
- );
109
-
110
- // Get stored assistants for the tenant
111
- const storeLattice = getStoreLattice("default", "assistant");
112
- const assistantStore = storeLattice.store;
113
- const storedAssistants = await assistantStore.getAllAssistants(tenantId);
114
-
115
- // Merge both sources, stored assistants take precedence if ID conflicts
116
- const assistantMap = new Map<string, Assistant>();
117
-
118
- // First add code-configured agents
119
- codeConfiguredAssistants.forEach((assistant) => {
120
- assistantMap.set(assistant.id, assistant);
121
- });
122
-
123
- // Then add stored assistants (overwrite if ID exists)
124
- storedAssistants.forEach((assistant) => {
125
- assistantMap.set(assistant.id, assistant);
126
- });
127
-
128
- const allAssistants = Array.from(assistantMap.values());
129
-
130
- // Filter: exclude personal assistants owned by other users
131
- const userId = getUserId(request);
132
- const filtered = allAssistants.filter((a) => {
133
- if (!a.ownerUserId) return true;
134
- return a.ownerUserId === userId;
135
- });
136
-
137
- return {
138
- success: true,
139
- message: "Successfully retrieved assistant list",
140
- data: {
141
- records: filtered,
142
- total: filtered.length,
143
- },
144
- };
145
- }
146
-
147
- /**
148
- * Get a single assistant by ID
149
- * Checks both code-configured agents and stored assistants
150
- */
151
- export async function getAssistant(
152
- request: FastifyRequest<{ Params: { id: string } }>,
153
- reply: FastifyReply
154
- ): Promise<AssistantResponse> {
155
- const { id } = request.params;
156
- const tenantId = getTenantId(request);
157
-
158
- // First check stored assistants
159
- const storeLattice = getStoreLattice("default", "assistant");
160
- const assistantStore = storeLattice.store;
161
- let assistant = await assistantStore.getAssistantById(tenantId, id);
162
-
163
- // If not found in store, check code-configured agents for the tenant
164
- if (!assistant) {
165
- const agentConfig = await agentLatticeManager.getAgentConfigWithTenant(tenantId, id);
166
- if (agentConfig) {
167
- assistant = convertAgentConfigToAssistant(agentConfig);
168
- }
169
- }
170
-
171
- if (!assistant) {
172
- return reply.status(404).send({
173
- success: false,
174
- message: "Assistant not found",
175
- });
176
- }
177
-
178
- return {
179
- success: true,
180
- message: "Successfully retrieved assistant",
181
- data: assistant,
182
- };
183
- }
184
-
185
- /**
186
- * Upsert assistant - create if not exists in store, update if exists
187
- */
188
- async function upsertAssistant(
189
- tenantId: string,
190
- id: string,
191
- data: CreateAssistantRequest | AssistantUpdateBody,
192
- reply: FastifyReply,
193
- requireFields: boolean = false
194
- ): Promise<AssistantResponse> {
195
- const storeLattice = getStoreLattice("default", "assistant");
196
- const assistantStore = storeLattice.store;
197
-
198
- const exists = await assistantStore.hasAssistant(tenantId, id);
199
-
200
- let assistant: Assistant | null;
201
- if (exists) {
202
- assistant = await assistantStore.updateAssistant(tenantId, id, data);
203
- if (!assistant) {
204
- return reply.status(500).send({
205
- success: false,
206
- message: "Failed to update assistant",
207
- });
208
- }
209
- eventBus.publish("assistant:updated", { id: assistant.id, name: assistant.name, tenantId });
210
- return {
211
- success: true,
212
- message: "Updated assistant",
213
- data: assistant,
214
- };
215
- }
216
-
217
- if (requireFields) {
218
- const createData = data as CreateAssistantRequest;
219
- if (!createData.name || !createData.graphDefinition) {
220
- return reply.status(400).send({
221
- success: false,
222
- message: "name and graphDefinition are required",
223
- });
224
- }
225
- }
226
-
227
- assistant = await assistantStore.createAssistant(tenantId, id, data as CreateAssistantRequest);
228
- eventBus.publish("assistant:created", { id: assistant.id, name: assistant.name, tenantId });
229
- return reply.status(201).send({
230
- success: true,
231
- message: "Created assistant",
232
- data: assistant,
233
- });
234
- }
235
-
236
- /**
237
- * Create a new assistant
238
- */
239
- export async function createAssistant(
240
- request: FastifyRequest<{ Body: CreateAssistantRequest & { id?: string } }>,
241
- reply: FastifyReply
242
- ): Promise<AssistantResponse> {
243
- const tenantId = getTenantId(request);
244
- const data = request.body;
245
-
246
- if (!data.name || !data.graphDefinition) {
247
- return reply.status(400).send({
248
- success: false,
249
- message: "name and graphDefinition are required",
250
- });
251
- }
252
-
253
- const id = data.id ?? randomUUID();
254
-
255
- // A2A_REMOTE: validate agentCardUrl, check localRuntime conflicts
256
- if (
257
- data.graphDefinition &&
258
- (data.graphDefinition as AgentConfig).type === AgentType.A2A_REMOTE
259
- ) {
260
- const a2aConfig = data.graphDefinition as A2ARemoteAgentConfig;
261
- const warnings: string[] = [];
262
- const isLocalManaged = !!a2aConfig.localRuntime;
263
- a2aConfig.agentCardUrl = normalizeA2AAgentCardUrl(
264
- a2aConfig.agentCardUrl,
265
- isLocalManaged ? "http://" : "https://",
266
- );
267
-
268
- if (a2aConfig.localRuntime) {
269
- const commandValidation = validateLocalRuntimeCommand(
270
- a2aConfig.localRuntime,
271
- );
272
- if (!commandValidation.ok) {
273
- return reply.status(400).send({
274
- success: false,
275
- message: commandValidation.error,
276
- });
277
- }
278
- a2aConfig.localRuntime.command.executable =
279
- a2aConfig.localRuntime.command.executable.trim();
280
-
281
- a2aConfig.localRuntime.agentCardUrl = normalizeA2AAgentCardUrl(
282
- a2aConfig.localRuntime.agentCardUrl || a2aConfig.agentCardUrl,
283
- "http://",
284
- );
285
- a2aConfig.agentCardUrl = a2aConfig.localRuntime.agentCardUrl;
286
-
287
- const portValidation = validateLocalRuntimePort(
288
- a2aConfig.localRuntime,
289
- a2aConfig.agentCardUrl,
290
- );
291
- if (!portValidation.ok) {
292
- return reply.status(400).send({
293
- success: false,
294
- message: portValidation.error,
295
- });
296
- }
297
- }
298
-
299
- if (a2aConfig.localRuntime) {
300
- const existingAssistants = await getStoreLattice("default", "assistant").store.getAllAssistants(tenantId);
301
- const targetPort = getAgentCardPort(a2aConfig.localRuntime.agentCardUrl);
302
- const duplicate = existingAssistants.find((a) => {
303
- if (a.id === id) return false;
304
- const gd = a.graphDefinition && typeof a.graphDefinition === "object"
305
- ? a.graphDefinition
306
- : undefined;
307
- if (!gd || (gd as { type?: unknown }).type !== AgentType.A2A_REMOTE) return false;
308
- const lr = (gd as A2ARemoteAgentConfig).localRuntime;
309
- if (!lr) return false;
310
- const existingAgentCardUrl = normalizeA2AAgentCardUrl(lr.agentCardUrl, "http://");
311
- const existingPort = getAgentCardPort(existingAgentCardUrl);
312
- if (targetPort !== null && existingPort !== null) {
313
- return existingPort === targetPort;
314
- }
315
- return existingAgentCardUrl === a2aConfig.localRuntime!.agentCardUrl;
316
- });
317
- if (duplicate) {
318
- const conflictDetail = targetPort === null
319
- ? `agentCardUrl "${a2aConfig.localRuntime.agentCardUrl}"`
320
- : `port ${targetPort}`;
321
- return reply.status(409).send({
322
- success: false,
323
- message: `A local managed A2A assistant using ${conflictDetail} already exists: "${duplicate.name}". Each local managed A2A assistant needs a unique port.`,
324
- });
325
- }
326
- }
327
-
328
- // Validate agentCardUrl reachability (non-blocking)
329
- try {
330
- const resp = await fetch(a2aConfig.agentCardUrl, {
331
- signal: AbortSignal.timeout(5000),
332
- });
333
- if (!resp.ok) {
334
- warnings.push(`agentCardUrl returned HTTP ${resp.status}`);
335
- }
336
- } catch {
337
- warnings.push(`agentCardUrl is not reachable: ${a2aConfig.agentCardUrl}`);
338
- }
339
-
340
- if (warnings.length > 0) {
341
- console.warn(`[createAssistant] A2A warnings for ${a2aConfig.agentCardUrl}:`, warnings);
342
- }
343
- }
344
-
345
- return upsertAssistant(tenantId, id, data, reply, true);
346
- }
347
-
348
- /**
349
- * Update an existing assistant by ID
350
- */
351
- export async function updateAssistant(
352
- request: FastifyRequest<{
353
- Params: { id: string };
354
- Body: AssistantUpdateBody;
355
- }>,
356
- reply: FastifyReply
357
- ): Promise<AssistantResponse> {
358
- const tenantId = getTenantId(request);
359
- const { id } = request.params;
360
- const updates = request.body;
361
-
362
- return upsertAssistant(tenantId, id, updates, reply, false);
363
- }
364
-
365
- /**
366
- * Delete an assistant by ID
367
- * For stored assistants: deletes from store
368
- * For local A2A agents: stops provider, unregisters from lattice, then deletes from store
369
- * For code-configured assistants: only deletes from store if exists (code registration remains)
370
- */
371
- export async function deleteAssistant(
372
- request: FastifyRequest<{ Params: { id: string } }>,
373
- reply: FastifyReply
374
- ): Promise<{ success: boolean; message: string }> {
375
- const tenantId = getTenantId(request);
376
- const { id } = request.params;
377
-
378
- const storeLattice = getStoreLattice("default", "assistant");
379
- const assistantStore = storeLattice.store;
380
-
381
- const storedAssistant = await assistantStore.getAssistantById(tenantId, id);
382
- const graphDefinition = storedAssistant?.graphDefinition;
383
- const hasLocalRuntime =
384
- graphDefinition && typeof graphDefinition === "object"
385
- ? !!(graphDefinition as A2ARemoteAgentConfig).localRuntime
386
- : false;
387
-
388
- if (storedAssistant && hasLocalRuntime) {
389
- localA2AService.removeState(id);
390
- const deleted = await assistantStore.deleteAssistant(tenantId, id);
391
- if (!deleted) {
392
- return reply.status(500).send({
393
- success: false,
394
- message: "Failed to delete assistant",
395
- });
396
- }
397
- eventBus.publish("assistant:deleted", { id, tenantId });
398
- return {
399
- success: true,
400
- message: "Deleted local A2A assistant",
401
- };
402
- }
403
-
404
- const agentConfig = await agentLatticeManager.getAgentConfigWithTenant(tenantId, id);
405
- const isCodeConfigured = !!agentConfig;
406
-
407
- if (isCodeConfigured) {
408
- if (!storedAssistant) {
409
- return reply.status(404).send({
410
- success: false,
411
- message: "Assistant not found (code-configured assistants cannot be deleted from code, only from store)",
412
- });
413
- }
414
- await assistantStore.deleteAssistant(tenantId, id);
415
- eventBus.publish("assistant:deleted", { id, tenantId });
416
- return {
417
- success: true,
418
- message: "Deleted assistant from store (code-configured registration remains)",
419
- };
420
- }
421
-
422
- if (!storedAssistant) {
423
- return reply.status(404).send({
424
- success: false,
425
- message: "Assistant not found",
426
- });
427
- }
428
-
429
- const deleted = await assistantStore.deleteAssistant(tenantId, id);
430
-
431
- if (!deleted) {
432
- return reply.status(500).send({
433
- success: false,
434
- message: "Failed to delete assistant",
435
- });
436
- }
437
-
438
- eventBus.publish("assistant:deleted", { id, tenantId });
439
-
440
- // Clean up UserTenantLink metadata if this was a personal assistant
441
- const userId = getUserId(request);
442
- if (userId) {
443
- try {
444
- const linkStore = getStoreLattice("default", "userTenantLink").store;
445
- const link = await linkStore.getLink(userId, tenantId);
446
- const meta = (link?.metadata || {}) as Record<string, unknown>;
447
- if (meta.personalAssistantId === id) {
448
- delete meta.personalAssistantId;
449
- delete meta.personalProjectId;
450
- delete meta.personalWorkspaceId;
451
- await linkStore.updateLink(userId, tenantId, { metadata: meta } as any);
452
- }
453
- } catch { /* best effort */ }
454
- }
455
-
456
- return {
457
- success: true,
458
- message: "Successfully deleted assistant",
459
- };
460
- }
461
-
462
- /**
463
- * Get agent graph visualization
464
- */
465
- export const getAgentGraph = async (
466
- request: FastifyRequest<{
467
- Params: { assistantId: string };
468
- }>,
469
- reply: FastifyReply
470
- ) => {
471
- try {
472
- const { assistantId } = request.params;
473
- const tenant_id = getTenantId(request);
474
-
475
- const agent = agentInstanceManager.getAgent({ assistant_id: assistantId, tenant_id, thread_id: '' })
476
-
477
- // Call drawing service to get image data
478
- const imageData = await agent.get_draw_graph()
479
-
480
- // Set response header and return image data
481
- reply.header("Content-Type", "application/json").send({
482
- image: imageData,
483
- });
484
- } catch (error: any) {
485
- reply.status(500).send({
486
- success: false,
487
- error: error.message || "Failed to get agent graph",
488
- });
489
- }
490
- };