@axiom-lattice/gateway 3.0.2 → 3.0.4

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 +37 -9
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.mjs +37 -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,213 +0,0 @@
1
- import { FastifyRequest, FastifyReply } from "fastify";
2
- import { getStoreLattice } from "@axiom-lattice/core";
3
- import type { TaskStore, TaskItem, CreateTaskRequest, UpdateTaskRequest, TaskWorkItemStore } from "@axiom-lattice/protocols";
4
-
5
- function getTenantId(request: FastifyRequest): string {
6
- const userTenantId = (request as any).user?.tenantId;
7
- if (userTenantId) return userTenantId;
8
- return (request.headers["x-tenant-id"] as string) || "default";
9
- }
10
-
11
- function getUserId(request: FastifyRequest): string {
12
- const userId = (request as any).user?.id
13
- || (request.headers["x-user-id"] as string);
14
- if (!userId) throw new Error("User ID is required");
15
- return userId;
16
- }
17
-
18
- function getStore(): TaskStore {
19
- return getStoreLattice("default", "task").store as TaskStore;
20
- }
21
-
22
- export async function listTasks(
23
- request: FastifyRequest,
24
- reply: FastifyReply
25
- ): Promise<{ success: boolean; data?: TaskItem[]; count?: number; error?: string }> {
26
- try {
27
- const tenantId = getTenantId(request);
28
- const query = request.query as Record<string, string>;
29
-
30
- const store = getStore();
31
- const tasks = await store.list({
32
- tenantId,
33
- status: query.status,
34
- priority: query.priority,
35
- ...(query.ownerId && { ownerId: query.ownerId }),
36
- ...(query.ownerType && { ownerType: query.ownerType as 'user' | 'agent' }),
37
- metadata: query.metadata ? JSON.parse(query.metadata) : undefined,
38
- projectId: query.projectId,
39
- limit: query.limit ? parseInt(query.limit) : undefined,
40
- offset: query.offset ? parseInt(query.offset) : undefined,
41
- });
42
-
43
- return { success: true, data: tasks, count: tasks.length };
44
- } catch (error: any) {
45
- return { success: false, error: error.message };
46
- }
47
- }
48
-
49
- export async function getTask(
50
- request: FastifyRequest<{ Params: { id: string } }>,
51
- reply: FastifyReply
52
- ): Promise<{ success: boolean; data?: TaskItem; error?: string }> {
53
- try {
54
- const tenantId = getTenantId(request);
55
- const userId = getUserId(request);
56
- const { id } = request.params;
57
-
58
- const store = getStore();
59
- const task = await store.getById(tenantId, id);
60
- if (!task) {
61
- return reply.status(404).send({ success: false, error: "Task not found" });
62
- }
63
-
64
- if (task.ownerType === 'user' && task.ownerId !== userId) {
65
- return reply.status(403).send({ success: false, error: "Access denied" });
66
- }
67
-
68
- return { success: true, data: task };
69
- } catch (error: any) {
70
- return { success: false, error: error.message };
71
- }
72
- }
73
-
74
- export async function createTask(
75
- request: FastifyRequest<{ Body: CreateTaskRequest }>,
76
- reply: FastifyReply
77
- ): Promise<{ success: boolean; data?: TaskItem; error?: string }> {
78
- try {
79
- const tenantId = getTenantId(request);
80
- const userId = getUserId(request);
81
- const body = request.body;
82
-
83
- if (!body.title) {
84
- return reply.status(400).send({ success: false, error: "title is required" });
85
- }
86
-
87
- const store = getStore();
88
- const task = await store.create({
89
- ...body,
90
- tenantId,
91
- ownerType: (body.ownerType || "user") as 'user' | 'agent',
92
- ownerId: body.ownerId || userId,
93
- });
94
-
95
- return reply.status(201).send({ success: true, data: task });
96
- } catch (error: any) {
97
- return reply.status(500).send({ success: false, error: error.message });
98
- }
99
- }
100
-
101
- export async function updateTask(
102
- request: FastifyRequest<{ Params: { id: string }; Body: UpdateTaskRequest }>,
103
- reply: FastifyReply
104
- ): Promise<{ success: boolean; data?: TaskItem; error?: string }> {
105
- try {
106
- const tenantId = getTenantId(request);
107
- const userId = getUserId(request);
108
- const { id } = request.params;
109
-
110
- const store = getStore();
111
- const existing = await store.getById(tenantId, id);
112
- if (!existing) {
113
- return reply.status(404).send({ success: false, error: "Task not found" });
114
- }
115
-
116
- if (existing.ownerType === 'user' && existing.ownerId !== userId) {
117
- return reply.status(403).send({ success: false, error: "Access denied" });
118
- }
119
-
120
- const task = await store.update(tenantId, id, request.body);
121
- if (!task) {
122
- return reply.status(404).send({ success: false, error: "Task not found" });
123
- }
124
- return { success: true, data: task };
125
- } catch (error: any) {
126
- return reply.status(500).send({ success: false, error: error.message });
127
- }
128
- }
129
-
130
- export async function deleteTask(
131
- request: FastifyRequest<{ Params: { id: string } }>,
132
- reply: FastifyReply
133
- ): Promise<{ success: boolean; message?: string; error?: string }> {
134
- try {
135
- const tenantId = getTenantId(request);
136
- const userId = getUserId(request);
137
- const { id } = request.params;
138
-
139
- const store = getStore();
140
- const existing = await store.getById(tenantId, id);
141
- if (!existing) {
142
- return reply.status(404).send({ success: false, error: "Task not found" });
143
- }
144
-
145
- if (existing.ownerType === 'user' && existing.ownerId !== userId) {
146
- return reply.status(403).send({ success: false, error: "Access denied" });
147
- }
148
-
149
- const deleted = await store.delete(tenantId, id);
150
- if (!deleted) {
151
- return reply.status(404).send({ success: false, error: "Task not found" });
152
- }
153
-
154
- return { success: true, message: "Task deleted" };
155
- } catch (error: any) {
156
- return reply.status(500).send({ success: false, error: error.message });
157
- }
158
- }
159
-
160
- export async function completeTask(
161
- request: FastifyRequest<{ Params: { id: string } }>,
162
- reply: FastifyReply
163
- ): Promise<{ success: boolean; data?: TaskItem; error?: string }> {
164
- try {
165
- const tenantId = getTenantId(request);
166
- const userId = getUserId(request);
167
- const { id } = request.params;
168
-
169
- const store = getStore();
170
- const existing = await store.getById(tenantId, id);
171
- if (!existing) {
172
- return reply.status(404).send({ success: false, error: "Task not found" });
173
- }
174
-
175
- if (existing.ownerType === 'user' && existing.ownerId !== userId) {
176
- return reply.status(403).send({ success: false, error: "Access denied" });
177
- }
178
-
179
- const task = await store.update(tenantId, id, { status: "completed" });
180
- if (!task) {
181
- return reply.status(404).send({ success: false, error: "Task not found" });
182
- }
183
- return { success: true, data: task };
184
- } catch (error: any) {
185
- return reply.status(500).send({ success: false, error: error.message });
186
- }
187
- }
188
-
189
- function getTaskWorkItemStore(): TaskWorkItemStore {
190
- return getStoreLattice("default", "taskWorkItem").store as TaskWorkItemStore;
191
- }
192
-
193
- export async function listTaskWorkItems(
194
- request: FastifyRequest<{
195
- Params: { id: string };
196
- Querystring: { action?: string; limit?: number; offset?: number }
197
- }>,
198
- reply: FastifyReply
199
- ) {
200
- const tenantId = getTenantId(request);
201
- const { id } = request.params;
202
- const { action, limit, offset } = request.query;
203
-
204
- const store = getTaskWorkItemStore();
205
- const items = await store.list({
206
- tenantId,
207
- taskId: id,
208
- action,
209
- limit: limit ? Number(limit) : undefined,
210
- offset: offset ? Number(offset) : undefined
211
- });
212
- return reply.send({ success: true, data: items });
213
- }
@@ -1,121 +0,0 @@
1
- /**
2
- * TenantsController
3
- *
4
- * Controller for tenant management
5
- * Handles CRUD operations for tenants (top-level entities)
6
- */
7
-
8
- import { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
9
- import { getStoreLattice } from "@axiom-lattice/core";
10
- import type {
11
- CreateTenantRequest,
12
- UpdateTenantRequest,
13
- } from "@axiom-lattice/protocols";
14
- import { v4 as uuidv4 } from "uuid";
15
-
16
- interface TenantParams {
17
- tenantId: string;
18
- }
19
-
20
- export class TenantsController {
21
- private tenantStore;
22
-
23
- constructor() {
24
- this.tenantStore = getStoreLattice("default", "tenant").store;
25
- }
26
-
27
- // ==================== Tenant CRUD ====================
28
-
29
- async listTenants(request: FastifyRequest, reply: FastifyReply) {
30
- const tenants = await this.tenantStore.getAllTenants();
31
- return { success: true, data: tenants };
32
- }
33
-
34
- async createTenant(
35
- request: FastifyRequest<{ Body: CreateTenantRequest }>,
36
- reply: FastifyReply
37
- ) {
38
- const data = request.body;
39
- const id = uuidv4();
40
-
41
- const tenant = await this.tenantStore.createTenant(id, data);
42
- return reply.status(201).send({ success: true, data: tenant });
43
- }
44
-
45
- async getTenant(
46
- request: FastifyRequest<{ Params: TenantParams }>,
47
- reply: FastifyReply
48
- ) {
49
- const { tenantId } = request.params;
50
-
51
- const tenant = await this.tenantStore.getTenantById(tenantId);
52
-
53
- if (!tenant) {
54
- return reply.status(404).send({
55
- success: false,
56
- error: "Tenant not found",
57
- });
58
- }
59
-
60
- return { success: true, data: tenant };
61
- }
62
-
63
- async updateTenant(
64
- request: FastifyRequest<{
65
- Params: TenantParams;
66
- Body: UpdateTenantRequest;
67
- }>,
68
- reply: FastifyReply
69
- ) {
70
- const { tenantId } = request.params;
71
- const updates = request.body;
72
-
73
- const tenant = await this.tenantStore.updateTenant(tenantId, updates);
74
-
75
- if (!tenant) {
76
- return reply.status(404).send({
77
- success: false,
78
- error: "Tenant not found",
79
- });
80
- }
81
-
82
- return { success: true, data: tenant };
83
- }
84
-
85
- async deleteTenant(
86
- request: FastifyRequest<{ Params: TenantParams }>,
87
- reply: FastifyReply
88
- ) {
89
- const { tenantId } = request.params;
90
-
91
- // Prevent deletion of the default tenant
92
- if (tenantId === "default") {
93
- return reply.status(403).send({
94
- success: false,
95
- error: "Cannot delete the default tenant",
96
- });
97
- }
98
-
99
- const deleted = await this.tenantStore.deleteTenant(tenantId);
100
-
101
- if (!deleted) {
102
- return reply.status(404).send({
103
- success: false,
104
- error: "Tenant not found",
105
- });
106
- }
107
-
108
- return { success: true };
109
- }
110
- }
111
-
112
- export function registerTenantRoutes(app: FastifyInstance) {
113
- const controller = new TenantsController();
114
-
115
- // Tenant routes
116
- app.get("/api/tenants", controller.listTenants.bind(controller));
117
- app.post("/api/tenants", controller.createTenant.bind(controller));
118
- app.get("/api/tenants/:tenantId", controller.getTenant.bind(controller));
119
- app.patch("/api/tenants/:tenantId", controller.updateTenant.bind(controller));
120
- app.delete("/api/tenants/:tenantId", controller.deleteTenant.bind(controller));
121
- }
@@ -1,66 +0,0 @@
1
- import { FastifyRequest, FastifyReply } from "fastify";
2
- import { agentInstanceManager } from "@axiom-lattice/core";
3
-
4
- /**
5
- * DELETE /api/assistants/:assistant_id/threads/:thread_id/pending-messages/:message_id
6
- * Remove pending message from queue
7
- */
8
- export async function removePendingMessageHandler(
9
- request: FastifyRequest,
10
- reply: FastifyReply
11
- ) {
12
- try {
13
- const { assistant_id, thread_id, message_id } = request.params as {
14
- assistant_id: string;
15
- thread_id: string;
16
- message_id: string;
17
- };
18
- const tenant_id = request.headers["x-tenant-id"] as string;
19
- const workspace_id = request.headers["x-workspace-id"] as string;
20
- const project_id = request.headers["x-project-id"] as string;
21
-
22
- if (!tenant_id) {
23
- return reply.code(400).send({ error: "Missing x-tenant-id header" });
24
- }
25
-
26
- if (!assistant_id) {
27
- return reply.code(400).send({ error: "Missing assistant_id parameter" });
28
- }
29
-
30
- // Get agent instance
31
- const agent = agentInstanceManager.getAgent({
32
- assistant_id,
33
- thread_id,
34
- tenant_id,
35
- workspace_id,
36
- project_id,
37
- });
38
-
39
- if (!agent) {
40
- return reply.code(404).send({
41
- error: "Thread not found",
42
- threadId: thread_id,
43
- });
44
- }
45
-
46
- const success = await agent.removePendingMessage(message_id);
47
-
48
- if (!success) {
49
- return reply.code(404).send({
50
- error: "Message not found",
51
- messageId: message_id,
52
- });
53
- }
54
-
55
- return reply.send({
56
- success: true,
57
- messageId: message_id,
58
- });
59
- } catch (error) {
60
- console.error("Error removing pending message:", error);
61
- return reply.code(500).send({
62
- error: "Internal server error",
63
- message: error instanceof Error ? error.message : String(error),
64
- });
65
- }
66
- }
@@ -1,260 +0,0 @@
1
- import { FastifyRequest, FastifyReply } from "fastify";
2
- import { getStoreLattice } from "@axiom-lattice/core";
3
- import { Thread, CreateThreadRequest } from "../types";
4
- import { randomUUID } from "crypto";
5
-
6
- /**
7
- * Thread Controller
8
- * Handles thread-related CRUD operations for a specific assistant
9
- * All operations are scoped to a tenant ID and assistant ID
10
- */
11
-
12
- /**
13
- * Get tenant ID from authenticated user context
14
- * Falls back to request headers for backward compatibility
15
- */
16
- function getTenantId(request: FastifyRequest): string {
17
- // First try to get from authenticated user context
18
- const userTenantId = (request as any).user?.tenantId;
19
- if (userTenantId) {
20
- return userTenantId;
21
- }
22
-
23
- // Fallback to request headers for backward compatibility
24
- return (request.headers["x-tenant-id"] as string) || "default";
25
- }
26
-
27
- /**
28
- * Thread list response interface
29
- */
30
- interface ThreadListResponse {
31
- success: boolean;
32
- message: string;
33
- data: {
34
- records: Thread[];
35
- total: number;
36
- };
37
- }
38
-
39
- /**
40
- * Thread response interface
41
- */
42
- interface ThreadResponse {
43
- success: boolean;
44
- message: string;
45
- data?: Thread;
46
- }
47
-
48
- /**
49
- * Thread update request body interface
50
- */
51
- interface ThreadUpdateBody {
52
- metadata?: Record<string, any>;
53
- }
54
-
55
- /**
56
- * Get list of all threads for a specific assistant
57
- */
58
- export async function getThreadList(
59
- request: FastifyRequest<{
60
- Params: { assistantId: string };
61
- }>,
62
- reply: FastifyReply
63
- ): Promise<ThreadListResponse> {
64
- const tenantId = getTenantId(request);
65
- const { assistantId } = request.params;
66
-
67
- // Build metadata filter from headers (workspace/project isolation)
68
- const metadataFilter: Record<string, string> = {};
69
- const workspaceId = request.headers["x-workspace-id"] as string | undefined;
70
- const projectId = request.headers["x-project-id"] as string | undefined;
71
-
72
- if (workspaceId) {
73
- metadataFilter.workspaceId = workspaceId;
74
- }
75
- if (projectId) {
76
- metadataFilter.projectId = projectId;
77
- }
78
-
79
- const storeLattice = getStoreLattice("default", "thread");
80
- const threadStore = storeLattice.store;
81
- const threads = await threadStore.getThreadsByAssistantId(
82
- tenantId,
83
- assistantId,
84
- Object.keys(metadataFilter).length > 0 ? metadataFilter : undefined
85
- );
86
-
87
- return {
88
- success: true,
89
- message: "Successfully retrieved thread list",
90
- data: {
91
- records: threads,
92
- total: threads.length,
93
- },
94
- };
95
- }
96
-
97
- /**
98
- * Get a single thread by ID for a specific tenant
99
- */
100
- export async function getThread(
101
- request: FastifyRequest<{
102
- Params: { assistantId: string; threadId: string };
103
- }>,
104
- reply: FastifyReply
105
- ): Promise<ThreadResponse> {
106
- const tenantId = getTenantId(request);
107
- const { threadId } = request.params;
108
-
109
- const storeLattice = getStoreLattice("default", "thread");
110
- const threadStore = storeLattice.store;
111
- const thread = await threadStore.getThreadById(tenantId, threadId);
112
-
113
- if (!thread) {
114
- return reply.status(404).send({
115
- success: false,
116
- message: "Thread not found",
117
- });
118
- }
119
-
120
- return {
121
- success: true,
122
- message: "Successfully retrieved thread",
123
- data: thread,
124
- };
125
- }
126
-
127
- /**
128
- * Create a new thread for an assistant
129
- */
130
- export async function createThread(
131
- request: FastifyRequest<{
132
- Params: { assistantId: string };
133
- Body: CreateThreadRequest;
134
- }>,
135
- reply: FastifyReply
136
- ): Promise<ThreadResponse> {
137
- const tenantId = getTenantId(request);
138
- const { assistantId } = request.params;
139
- const data = request.body;
140
-
141
- // Generate thread ID if not provided
142
- const threadId = randomUUID();
143
-
144
- // Extract workspace and project from headers
145
- const workspaceId = request.headers["x-workspace-id"] as string | undefined;
146
- const projectId = request.headers["x-project-id"] as string | undefined;
147
-
148
- // Enrich metadata with tenant/workspace/project
149
- const enrichedMetadata: Record<string, any> = {
150
- ...data.metadata,
151
- tenantId,
152
- };
153
-
154
- if (workspaceId) {
155
- enrichedMetadata.workspaceId = workspaceId;
156
- }
157
- if (projectId) {
158
- enrichedMetadata.projectId = projectId;
159
- }
160
-
161
- // Create thread with enriched metadata
162
- const storeLattice = getStoreLattice("default", "thread");
163
- const threadStore = storeLattice.store;
164
- const newThread = await threadStore.createThread(tenantId, assistantId, threadId, {
165
- metadata: enrichedMetadata,
166
- });
167
-
168
- return reply.status(201).send({
169
- success: true,
170
- message: "Successfully created thread",
171
- data: newThread,
172
- });
173
- }
174
-
175
- /**
176
- * Update an existing thread by ID
177
- */
178
- export async function updateThread(
179
- request: FastifyRequest<{
180
- Params: { assistantId: string; threadId: string };
181
- Body: ThreadUpdateBody;
182
- }>,
183
- reply: FastifyReply
184
- ): Promise<ThreadResponse> {
185
- const tenantId = getTenantId(request);
186
- const { threadId } = request.params;
187
- const updates = request.body;
188
-
189
- const storeLattice = getStoreLattice("default", "thread");
190
- const threadStore = storeLattice.store;
191
-
192
- // Check if thread exists
193
- const exists = await threadStore.hasThread(tenantId, threadId);
194
- if (!exists) {
195
- return reply.status(404).send({
196
- success: false,
197
- message: "Thread not found",
198
- });
199
- }
200
-
201
- // Update thread
202
- const updatedThread = await threadStore.updateThread(
203
- tenantId,
204
- threadId,
205
- updates
206
- );
207
-
208
- if (!updatedThread) {
209
- return reply.status(500).send({
210
- success: false,
211
- message: "Failed to update thread",
212
- });
213
- }
214
-
215
- return {
216
- success: true,
217
- message: "Successfully updated thread",
218
- data: updatedThread,
219
- };
220
- }
221
-
222
- /**
223
- * Delete a thread by ID
224
- */
225
- export async function deleteThread(
226
- request: FastifyRequest<{
227
- Params: { assistantId: string; threadId: string };
228
- }>,
229
- reply: FastifyReply
230
- ): Promise<{ success: boolean; message: string }> {
231
- const tenantId = getTenantId(request);
232
- const { threadId } = request.params;
233
-
234
- const storeLattice = getStoreLattice("default", "thread");
235
- const threadStore = storeLattice.store;
236
-
237
- // Check if thread exists
238
- const exists = await threadStore.hasThread(tenantId, threadId);
239
- if (!exists) {
240
- return reply.status(404).send({
241
- success: false,
242
- message: "Thread not found",
243
- });
244
- }
245
-
246
- // Delete the thread
247
- const deleted = await threadStore.deleteThread(tenantId, threadId);
248
-
249
- if (!deleted) {
250
- return reply.status(500).send({
251
- success: false,
252
- message: "Failed to delete thread",
253
- });
254
- }
255
-
256
- return {
257
- success: true,
258
- message: "Successfully deleted thread",
259
- };
260
- }