@axiom-lattice/gateway 2.1.38 → 2.1.39

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.
@@ -8,8 +8,23 @@ import {
8
8
  /**
9
9
  * Schedule Controller
10
10
  * Handles schedule-related operations for viewing and managing scheduled tasks
11
+ * All operations are scoped to a tenant ID
11
12
  */
12
13
 
14
+ /**
15
+ * Get tenant ID from request headers or user context
16
+ */
17
+ function getTenantId(request: FastifyRequest): string {
18
+ // First try to get from authenticated user context
19
+ const userTenantId = (request as any).user?.tenantId;
20
+ if (userTenantId) {
21
+ return userTenantId;
22
+ }
23
+
24
+ // Fallback to request headers for backward compatibility
25
+ return (request.headers["x-tenant-id"] as string) || "default";
26
+ }
27
+
13
28
  /**
14
29
  * Scheduled tasks list response interface
15
30
  */
@@ -93,13 +108,17 @@ export async function getThreadSchedules(
93
108
  };
94
109
  }
95
110
 
111
+ const tenantId = getTenantId(request);
112
+
96
113
  const filters: {
114
+ tenantId: string;
97
115
  threadId: string;
98
116
  assistantId?: string;
99
117
  status?: ScheduledTaskStatus;
100
118
  limit?: number;
101
119
  offset?: number;
102
120
  } = {
121
+ tenantId,
103
122
  threadId,
104
123
  assistantId,
105
124
  };
@@ -116,6 +135,7 @@ export async function getThreadSchedules(
116
135
 
117
136
  const tasks = await storage.getAllTasks(filters);
118
137
  const total = await storage.countTasks({
138
+ tenantId,
119
139
  threadId,
120
140
  assistantId,
121
141
  status,
@@ -6,6 +6,21 @@ import type {
6
6
  CreateSkillRequest,
7
7
  } from "@axiom-lattice/protocols";
8
8
 
9
+ /**
10
+ * Get tenant ID from authenticated user context
11
+ * Falls back to request headers for backward compatibility
12
+ */
13
+ function getTenantId(request: FastifyRequest): string {
14
+ // First try to get from authenticated user context
15
+ const userTenantId = (request as any).user?.tenantId;
16
+ if (userTenantId) {
17
+ return userTenantId;
18
+ }
19
+
20
+ // Fallback to request headers for backward compatibility
21
+ return (request.headers["x-tenant-id"] as string) || "default";
22
+ }
23
+
9
24
  /**
10
25
  * Skills Controller
11
26
  * Handles skill-related CRUD operations
@@ -84,9 +99,10 @@ export async function getSkillList(
84
99
  reply: FastifyReply
85
100
  ): Promise<SkillListResponse> {
86
101
  try {
102
+ const tenantId = getTenantId(request);
87
103
  const storeLattice = getStoreLattice("default", "skill");
88
104
  const skillStore = storeLattice.store;
89
- const skills = await skillStore.getAllSkills();
105
+ const skills = await skillStore.getAllSkills(tenantId);
90
106
 
91
107
  // Serialize skills to convert Date objects to ISO strings
92
108
  const serializedSkills = skills.map(serializeSkill);
@@ -119,11 +135,12 @@ export async function getSkill(
119
135
  reply: FastifyReply
120
136
  ): Promise<SkillResponse> {
121
137
  try {
138
+ const tenantId = getTenantId(request);
122
139
  const { id } = request.params;
123
140
 
124
141
  const storeLattice = getStoreLattice("default", "skill");
125
142
  const skillStore = storeLattice.store;
126
- const skill = await skillStore.getSkillById(id);
143
+ const skill = await skillStore.getSkillById(tenantId, id);
127
144
 
128
145
  if (!skill) {
129
146
  return reply.status(404).send({
@@ -190,11 +207,12 @@ export async function createSkill(
190
207
  });
191
208
  }
192
209
 
210
+ const tenantId = getTenantId(request);
193
211
  const storeLattice = getStoreLattice("default", "skill");
194
212
  const skillStore = storeLattice.store;
195
213
 
196
214
  // Check if skill already exists
197
- const exists = await skillStore.hasSkill(id);
215
+ const exists = await skillStore.hasSkill(tenantId, id);
198
216
  if (exists) {
199
217
  return reply.status(409).send({
200
218
  success: false,
@@ -203,7 +221,7 @@ export async function createSkill(
203
221
  }
204
222
 
205
223
  // Create skill
206
- const newSkill = await skillStore.createSkill(id, data);
224
+ const newSkill = await skillStore.createSkill(tenantId, id, data);
207
225
 
208
226
  return reply.status(201).send({
209
227
  success: true,
@@ -244,11 +262,12 @@ export async function updateSkill(
244
262
  }
245
263
  }
246
264
 
265
+ const tenantId = getTenantId(request);
247
266
  const storeLattice = getStoreLattice("default", "skill");
248
267
  const skillStore = storeLattice.store;
249
268
 
250
269
  // Check if skill exists
251
- const exists = await skillStore.hasSkill(id);
270
+ const exists = await skillStore.hasSkill(tenantId, id);
252
271
  if (!exists) {
253
272
  return reply.status(404).send({
254
273
  success: false,
@@ -257,7 +276,7 @@ export async function updateSkill(
257
276
  }
258
277
 
259
278
  // Update skill
260
- const updatedSkill = await skillStore.updateSkill(id, updates);
279
+ const updatedSkill = await skillStore.updateSkill(tenantId, id, updates);
261
280
 
262
281
  if (!updatedSkill) {
263
282
  return reply.status(500).send({
@@ -289,11 +308,12 @@ export async function deleteSkill(
289
308
  try {
290
309
  const { id } = request.params;
291
310
 
311
+ const tenantId = getTenantId(request);
292
312
  const storeLattice = getStoreLattice("default", "skill");
293
313
  const skillStore = storeLattice.store;
294
314
 
295
315
  // Check if skill exists
296
- const exists = await skillStore.hasSkill(id);
316
+ const exists = await skillStore.hasSkill(tenantId, id);
297
317
  if (!exists) {
298
318
  return reply.status(404).send({
299
319
  success: false,
@@ -302,7 +322,7 @@ export async function deleteSkill(
302
322
  }
303
323
 
304
324
  // Delete the skill
305
- const deleted = await skillStore.deleteSkill(id);
325
+ const deleted = await skillStore.deleteSkill(tenantId, id);
306
326
 
307
327
  if (!deleted) {
308
328
  return reply.status(500).send({
@@ -346,9 +366,10 @@ export async function searchSkillsByMetadata(
346
366
  });
347
367
  }
348
368
 
369
+ const tenantId = getTenantId(request);
349
370
  const storeLattice = getStoreLattice("default", "skill");
350
371
  const skillStore = storeLattice.store;
351
- const skills = await skillStore.searchByMetadata(key, value);
372
+ const skills = await skillStore.searchByMetadata(tenantId, key, value);
352
373
 
353
374
  // Serialize skills to convert Date objects to ISO strings
354
375
  const serializedSkills = skills.map(serializeSkill);
@@ -396,9 +417,10 @@ export async function filterSkillsByCompatibility(
396
417
  });
397
418
  }
398
419
 
420
+ const tenantId = getTenantId(request);
399
421
  const storeLattice = getStoreLattice("default", "skill");
400
422
  const skillStore = storeLattice.store;
401
- const skills = await skillStore.filterByCompatibility(compatibility);
423
+ const skills = await skillStore.filterByCompatibility(tenantId, compatibility);
402
424
 
403
425
  // Serialize skills to convert Date objects to ISO strings
404
426
  const serializedSkills = skills.map(serializeSkill);
@@ -446,9 +468,10 @@ export async function filterSkillsByLicense(
446
468
  });
447
469
  }
448
470
 
471
+ const tenantId = getTenantId(request);
449
472
  const storeLattice = getStoreLattice("default", "skill");
450
473
  const skillStore = storeLattice.store;
451
- const skills = await skillStore.filterByLicense(license);
474
+ const skills = await skillStore.filterByLicense(tenantId, license);
452
475
 
453
476
  // Serialize skills to convert Date objects to ISO strings
454
477
  const serializedSkills = skills.map(serializeSkill);
@@ -6,9 +6,24 @@ import { randomUUID } from "crypto";
6
6
  /**
7
7
  * Thread Controller
8
8
  * Handles thread-related CRUD operations for a specific assistant
9
- * All operations are scoped to an assistant ID
9
+ * All operations are scoped to a tenant ID and assistant ID
10
10
  */
11
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
+
12
27
  /**
13
28
  * Thread list response interface
14
29
  */
@@ -44,11 +59,12 @@ export async function getThreadList(
44
59
  request: FastifyRequest<{ Params: { assistantId: string } }>,
45
60
  reply: FastifyReply
46
61
  ): Promise<ThreadListResponse> {
62
+ const tenantId = getTenantId(request);
47
63
  const { assistantId } = request.params;
48
64
 
49
65
  const storeLattice = getStoreLattice("default", "thread");
50
66
  const threadStore = storeLattice.store;
51
- const threads = await threadStore.getThreadsByAssistantId(assistantId);
67
+ const threads = await threadStore.getThreadsByAssistantId(tenantId, assistantId);
52
68
 
53
69
  return {
54
70
  success: true,
@@ -61,7 +77,7 @@ export async function getThreadList(
61
77
  }
62
78
 
63
79
  /**
64
- * Get a single thread by ID for a specific assistant
80
+ * Get a single thread by ID for a specific tenant
65
81
  */
66
82
  export async function getThread(
67
83
  request: FastifyRequest<{
@@ -69,11 +85,12 @@ export async function getThread(
69
85
  }>,
70
86
  reply: FastifyReply
71
87
  ): Promise<ThreadResponse> {
72
- const { assistantId, threadId } = request.params;
88
+ const tenantId = getTenantId(request);
89
+ const { threadId } = request.params;
73
90
 
74
91
  const storeLattice = getStoreLattice("default", "thread");
75
92
  const threadStore = storeLattice.store;
76
- const thread = await threadStore.getThreadById(assistantId, threadId);
93
+ const thread = await threadStore.getThreadById(tenantId, threadId);
77
94
 
78
95
  if (!thread) {
79
96
  return reply.status(404).send({
@@ -99,6 +116,7 @@ export async function createThread(
99
116
  }>,
100
117
  reply: FastifyReply
101
118
  ): Promise<ThreadResponse> {
119
+ const tenantId = getTenantId(request);
102
120
  const { assistantId } = request.params;
103
121
  const data = request.body;
104
122
 
@@ -108,7 +126,7 @@ export async function createThread(
108
126
  // Create thread
109
127
  const storeLattice = getStoreLattice("default", "thread");
110
128
  const threadStore = storeLattice.store;
111
- const newThread = await threadStore.createThread(assistantId, threadId, data);
129
+ const newThread = await threadStore.createThread(tenantId, assistantId, threadId, data);
112
130
 
113
131
  return reply.status(201).send({
114
132
  success: true,
@@ -127,14 +145,15 @@ export async function updateThread(
127
145
  }>,
128
146
  reply: FastifyReply
129
147
  ): Promise<ThreadResponse> {
130
- const { assistantId, threadId } = request.params;
148
+ const tenantId = getTenantId(request);
149
+ const { threadId } = request.params;
131
150
  const updates = request.body;
132
151
 
133
152
  const storeLattice = getStoreLattice("default", "thread");
134
153
  const threadStore = storeLattice.store;
135
154
 
136
155
  // Check if thread exists
137
- const exists = await threadStore.hasThread(assistantId, threadId);
156
+ const exists = await threadStore.hasThread(tenantId, threadId);
138
157
  if (!exists) {
139
158
  return reply.status(404).send({
140
159
  success: false,
@@ -144,7 +163,7 @@ export async function updateThread(
144
163
 
145
164
  // Update thread
146
165
  const updatedThread = await threadStore.updateThread(
147
- assistantId,
166
+ tenantId,
148
167
  threadId,
149
168
  updates
150
169
  );
@@ -172,13 +191,14 @@ export async function deleteThread(
172
191
  }>,
173
192
  reply: FastifyReply
174
193
  ): Promise<{ success: boolean; message: string }> {
175
- const { assistantId, threadId } = request.params;
194
+ const tenantId = getTenantId(request);
195
+ const { threadId } = request.params;
176
196
 
177
197
  const storeLattice = getStoreLattice("default", "thread");
178
198
  const threadStore = storeLattice.store;
179
199
 
180
200
  // Check if thread exists
181
- const exists = await threadStore.hasThread(assistantId, threadId);
201
+ const exists = await threadStore.hasThread(tenantId, threadId);
182
202
  if (!exists) {
183
203
  return reply.status(404).send({
184
204
  success: false,
@@ -187,7 +207,7 @@ export async function deleteThread(
187
207
  }
188
208
 
189
209
  // Delete the thread
190
- const deleted = await threadStore.deleteThread(assistantId, threadId);
210
+ const deleted = await threadStore.deleteThread(tenantId, threadId);
191
211
 
192
212
  if (!deleted) {
193
213
  return reply.status(500).send({
@@ -1,285 +1,14 @@
1
1
  import { FastifyRequest, FastifyReply } from "fastify";
2
- import { getStoreLattice, toolLatticeManager } from "@axiom-lattice/core";
2
+ import { toolLatticeManager } from "@axiom-lattice/core";
3
3
  import type {
4
- Tool,
5
4
  ToolConfig,
6
5
  } from "@axiom-lattice/protocols";
7
6
 
8
7
  /**
9
8
  * Tools Controller
10
- * Handles tool-related CRUD operations
9
+ * Handles tool-related operations
11
10
  */
12
11
 
13
- /**
14
- * Tool list response interface
15
- */
16
- interface ToolListResponse {
17
- success: boolean;
18
- message: string;
19
- data: {
20
- records: Tool[];
21
- total: number;
22
- };
23
- }
24
-
25
- /**
26
- * Tool response interface
27
- */
28
- interface ToolResponse {
29
- success: boolean;
30
- message: string;
31
- data?: Tool;
32
- }
33
-
34
- /**
35
- * Serialize Tool object for JSON response
36
- * Converts Date objects to ISO strings
37
- * Explicitly creates a plain object to ensure all fields are serializable
38
- */
39
- function serializeTool(tool: Tool): any {
40
- // Explicitly create a plain object with all fields
41
- // This ensures Fastify can properly serialize the response
42
- const serialized: any = {
43
- id: tool.id,
44
- name: tool.name,
45
- description: tool.description,
46
- license: tool.license,
47
- compatibility: tool.compatibility,
48
- metadata: tool.metadata || {},
49
- config: tool.config,
50
- createdAt: tool.createdAt instanceof Date ? tool.createdAt.toISOString() : (tool.createdAt ? new Date(tool.createdAt).toISOString() : new Date().toISOString()),
51
- updatedAt: tool.updatedAt instanceof Date ? tool.updatedAt.toISOString() : (tool.updatedAt ? new Date(tool.updatedAt).toISOString() : new Date().toISOString()),
52
- };
53
-
54
- // Remove undefined fields to avoid serialization issues
55
- Object.keys(serialized).forEach((key) => {
56
- if (serialized[key] === undefined) {
57
- delete serialized[key];
58
- }
59
- });
60
-
61
- return serialized;
62
- }
63
-
64
- /**
65
- * Get list of all tools
66
- */
67
- export async function getToolList(
68
- request: FastifyRequest,
69
- reply: FastifyReply
70
- ): Promise<ToolListResponse> {
71
- try {
72
- const storeLattice = getStoreLattice("default", "tool");
73
- const toolStore = storeLattice.store;
74
- const tools = await toolStore.getAllTools();
75
-
76
- // Serialize tools to convert Date objects to ISO strings
77
- const serializedTools = tools.map(serializeTool);
78
-
79
- return {
80
- success: true,
81
- message: "Successfully retrieved tool list",
82
- data: {
83
- records: serializedTools,
84
- total: serializedTools.length,
85
- },
86
- };
87
- } catch (error: any) {
88
- return reply.status(500).send({
89
- success: false,
90
- message: `Failed to retrieve tools: ${error.message}`,
91
- data: {
92
- records: [],
93
- total: 0,
94
- },
95
- });
96
- }
97
- }
98
-
99
- /**
100
- * Get a single tool by ID
101
- */
102
- export async function getTool(
103
- request: FastifyRequest<{ Params: { id: string } }>,
104
- reply: FastifyReply
105
- ): Promise<ToolResponse> {
106
- try {
107
- const { id } = request.params;
108
-
109
- const storeLattice = getStoreLattice("default", "tool");
110
- const toolStore = storeLattice.store;
111
- const tool = await toolStore.getToolById(id);
112
-
113
- if (!tool) {
114
- return reply.status(404).send({
115
- success: false,
116
- message: "Tool not found",
117
- });
118
- }
119
-
120
- return {
121
- success: true,
122
- message: "Successfully retrieved tool",
123
- data: serializeTool(tool),
124
- };
125
- } catch (error: any) {
126
- return reply.status(500).send({
127
- success: false,
128
- message: `Failed to retrieve tool: ${error.message}`,
129
- });
130
- }
131
- }
132
-
133
- /**
134
- * Search tools by metadata
135
- */
136
- export async function searchToolsByMetadata(
137
- request: FastifyRequest<{
138
- Querystring: { key: string; value: string };
139
- }>,
140
- reply: FastifyReply
141
- ): Promise<ToolListResponse> {
142
- try {
143
- const { key, value } = request.query;
144
-
145
- if (!key || !value) {
146
- return reply.status(400).send({
147
- success: false,
148
- message: "key and value query parameters are required",
149
- data: {
150
- records: [],
151
- total: 0,
152
- },
153
- });
154
- }
155
-
156
- const storeLattice = getStoreLattice("default", "tool");
157
- const toolStore = storeLattice.store;
158
- const tools = await toolStore.searchByMetadata(key, value);
159
-
160
- // Serialize tools to convert Date objects to ISO strings
161
- const serializedTools = tools.map(serializeTool);
162
-
163
- return {
164
- success: true,
165
- message: "Successfully searched tools",
166
- data: {
167
- records: serializedTools,
168
- total: serializedTools.length,
169
- },
170
- };
171
- } catch (error: any) {
172
- return reply.status(500).send({
173
- success: false,
174
- message: `Failed to search tools: ${error.message}`,
175
- data: {
176
- records: [],
177
- total: 0,
178
- },
179
- });
180
- }
181
- }
182
-
183
- /**
184
- * Filter tools by compatibility
185
- */
186
- export async function filterToolsByCompatibility(
187
- request: FastifyRequest<{
188
- Querystring: { compatibility: string };
189
- }>,
190
- reply: FastifyReply
191
- ): Promise<ToolListResponse> {
192
- try {
193
- const { compatibility } = request.query;
194
-
195
- if (!compatibility) {
196
- return reply.status(400).send({
197
- success: false,
198
- message: "compatibility query parameter is required",
199
- data: {
200
- records: [],
201
- total: 0,
202
- },
203
- });
204
- }
205
-
206
- const storeLattice = getStoreLattice("default", "tool");
207
- const toolStore = storeLattice.store;
208
- const tools = await toolStore.filterByCompatibility(compatibility);
209
-
210
- // Serialize tools to convert Date objects to ISO strings
211
- const serializedTools = tools.map(serializeTool);
212
-
213
- return {
214
- success: true,
215
- message: "Successfully filtered tools",
216
- data: {
217
- records: serializedTools,
218
- total: serializedTools.length,
219
- },
220
- };
221
- } catch (error: any) {
222
- return reply.status(500).send({
223
- success: false,
224
- message: `Failed to filter tools: ${error.message}`,
225
- data: {
226
- records: [],
227
- total: 0,
228
- },
229
- });
230
- }
231
- }
232
-
233
- /**
234
- * Filter tools by license
235
- */
236
- export async function filterToolsByLicense(
237
- request: FastifyRequest<{
238
- Querystring: { license: string };
239
- }>,
240
- reply: FastifyReply
241
- ): Promise<ToolListResponse> {
242
- try {
243
- const { license } = request.query;
244
-
245
- if (!license) {
246
- return reply.status(400).send({
247
- success: false,
248
- message: "license query parameter is required",
249
- data: {
250
- records: [],
251
- total: 0,
252
- },
253
- });
254
- }
255
-
256
- const storeLattice = getStoreLattice("default", "tool");
257
- const toolStore = storeLattice.store;
258
- const tools = await toolStore.filterByLicense(license);
259
-
260
- // Serialize tools to convert Date objects to ISO strings
261
- const serializedTools = tools.map(serializeTool);
262
-
263
- return {
264
- success: true,
265
- message: "Successfully filtered tools",
266
- data: {
267
- records: serializedTools,
268
- total: serializedTools.length,
269
- },
270
- };
271
- } catch (error: any) {
272
- return reply.status(500).send({
273
- success: false,
274
- message: `Failed to filter tools: ${error.message}`,
275
- data: {
276
- records: [],
277
- total: 0,
278
- },
279
- });
280
- }
281
- }
282
-
283
12
  /**
284
13
  * Tool config meta response interface
285
14
  */