@axiom-lattice/gateway 2.1.53 → 2.1.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +19 -0
- package/dist/index.js +1043 -526
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +977 -449
- package/dist/index.mjs.map +1 -1
- package/jest.config.js +5 -0
- package/package.json +6 -5
- package/src/__tests__/__mocks__/e2b.ts +1 -0
- package/src/__tests__/channel-installations.test.ts +199 -0
- package/src/__tests__/sandbox-provider-registration.test.ts +74 -0
- package/src/__tests__/workspace.test.ts +119 -8
- package/src/channels/__tests__/routes.test.ts +71 -0
- package/src/channels/lark/README.md +187 -0
- package/src/channels/lark/__tests__/aggregator.test.ts +23 -0
- package/src/channels/lark/__tests__/controller.test.ts +270 -0
- package/src/channels/lark/__tests__/mapping-service.test.ts +118 -0
- package/src/channels/lark/__tests__/parser.test.ts +72 -0
- package/src/channels/lark/__tests__/sender.test.ts +37 -0
- package/src/channels/lark/__tests__/verification.test.ts +157 -0
- package/src/channels/lark/aggregator.ts +16 -0
- package/src/channels/lark/config.ts +44 -0
- package/src/channels/lark/controller.ts +189 -0
- package/src/channels/lark/mapping-service.ts +138 -0
- package/src/channels/lark/parser.ts +68 -0
- package/src/channels/lark/routes.ts +121 -0
- package/src/channels/lark/runner.ts +37 -0
- package/src/channels/lark/sender.ts +58 -0
- package/src/channels/lark/types.ts +33 -0
- package/src/channels/lark/verification.ts +67 -0
- package/src/channels/routes.ts +25 -0
- package/src/controllers/channel-installations.ts +354 -0
- package/src/controllers/sandbox.ts +30 -80
- package/src/controllers/skills.ts +71 -321
- package/src/controllers/threads.ts +8 -6
- package/src/controllers/workspace.ts +64 -179
- package/src/index.ts +28 -5
- package/src/routes/channel-installations.ts +33 -0
- package/src/routes/index.ts +6 -0
- package/src/schemas/index.ts +2 -2
- package/src/services/sandbox_service.ts +21 -21
- package/src/services/skill_service.ts +97 -0
|
@@ -1,55 +1,40 @@
|
|
|
1
1
|
import { FastifyRequest, FastifyReply } from "fastify";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
5
|
-
Skill,
|
|
6
|
-
CreateSkillRequest,
|
|
7
|
-
} from "@axiom-lattice/protocols";
|
|
2
|
+
import { SkillService } from "../services/skill_service";
|
|
3
|
+
import type { Skill, CreateSkillRequest } from "@axiom-lattice/protocols";
|
|
8
4
|
|
|
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
|
-
}
|
|
5
|
+
const skillService = new SkillService();
|
|
19
6
|
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
function serializeSkill(skill: Skill): any {
|
|
8
|
+
const serialized: any = {
|
|
9
|
+
id: skill.id,
|
|
10
|
+
name: skill.name,
|
|
11
|
+
description: skill.description,
|
|
12
|
+
license: skill.license,
|
|
13
|
+
compatibility: skill.compatibility,
|
|
14
|
+
metadata: skill.metadata || {},
|
|
15
|
+
content: skill.content,
|
|
16
|
+
subSkills: skill.subSkills,
|
|
17
|
+
createdAt: skill.createdAt instanceof Date ? skill.createdAt.toISOString() : new Date().toISOString(),
|
|
18
|
+
updatedAt: skill.updatedAt instanceof Date ? skill.updatedAt.toISOString() : new Date().toISOString(),
|
|
19
|
+
};
|
|
20
|
+
Object.keys(serialized).forEach((key) => {
|
|
21
|
+
if (serialized[key] === undefined) delete serialized[key];
|
|
22
|
+
});
|
|
23
|
+
return serialized;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
/**
|
|
25
|
-
* Skills Controller
|
|
26
|
-
* Handles skill-related CRUD operations
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Skill list response interface
|
|
31
|
-
*/
|
|
32
26
|
interface SkillListResponse {
|
|
33
27
|
success: boolean;
|
|
34
28
|
message: string;
|
|
35
|
-
data: {
|
|
36
|
-
records: Skill[];
|
|
37
|
-
total: number;
|
|
38
|
-
};
|
|
29
|
+
data: { records: any[]; total: number };
|
|
39
30
|
}
|
|
40
31
|
|
|
41
|
-
/**
|
|
42
|
-
* Skill response interface
|
|
43
|
-
*/
|
|
44
32
|
interface SkillResponse {
|
|
45
33
|
success: boolean;
|
|
46
34
|
message: string;
|
|
47
|
-
data?:
|
|
35
|
+
data?: any;
|
|
48
36
|
}
|
|
49
37
|
|
|
50
|
-
/**
|
|
51
|
-
* Skill update request body interface
|
|
52
|
-
*/
|
|
53
38
|
interface SkillUpdateBody {
|
|
54
39
|
name?: string;
|
|
55
40
|
description?: string;
|
|
@@ -60,438 +45,203 @@ interface SkillUpdateBody {
|
|
|
60
45
|
subSkills?: string[];
|
|
61
46
|
}
|
|
62
47
|
|
|
63
|
-
|
|
64
|
-
* Serialize Skill object for JSON response
|
|
65
|
-
* Converts Date objects to ISO strings
|
|
66
|
-
* Explicitly creates a plain object to ensure all fields are serializable
|
|
67
|
-
*/
|
|
68
|
-
function serializeSkill(skill: Skill): any {
|
|
69
|
-
// Explicitly create a plain object with all fields
|
|
70
|
-
// This ensures Fastify can properly serialize the response
|
|
71
|
-
const serialized: any = {
|
|
72
|
-
id: skill.id,
|
|
73
|
-
name: skill.name,
|
|
74
|
-
description: skill.description,
|
|
75
|
-
license: skill.license,
|
|
76
|
-
compatibility: skill.compatibility,
|
|
77
|
-
metadata: skill.metadata || {},
|
|
78
|
-
content: skill.content,
|
|
79
|
-
subSkills: skill.subSkills,
|
|
80
|
-
createdAt: skill.createdAt instanceof Date ? skill.createdAt.toISOString() : (skill.createdAt ? new Date(skill.createdAt).toISOString() : new Date().toISOString()),
|
|
81
|
-
updatedAt: skill.updatedAt instanceof Date ? skill.updatedAt.toISOString() : (skill.updatedAt ? new Date(skill.updatedAt).toISOString() : new Date().toISOString()),
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// Remove undefined fields to avoid serialization issues
|
|
85
|
-
Object.keys(serialized).forEach((key) => {
|
|
86
|
-
if (serialized[key] === undefined) {
|
|
87
|
-
delete serialized[key];
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
return serialized;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Get list of all skills
|
|
96
|
-
*/
|
|
97
|
-
export async function getSkillList(
|
|
98
|
-
request: FastifyRequest,
|
|
99
|
-
reply: FastifyReply
|
|
100
|
-
): Promise<SkillListResponse> {
|
|
48
|
+
export async function getSkillList(request: FastifyRequest, reply: FastifyReply): Promise<SkillListResponse> {
|
|
101
49
|
try {
|
|
102
|
-
const
|
|
103
|
-
const storeLattice = getStoreLattice("default", "skill");
|
|
104
|
-
const skillStore = storeLattice.store;
|
|
105
|
-
const skills = await skillStore.getAllSkills(tenantId);
|
|
106
|
-
|
|
107
|
-
// Serialize skills to convert Date objects to ISO strings
|
|
108
|
-
const serializedSkills = skills.map(serializeSkill);
|
|
109
|
-
|
|
50
|
+
const skills = await skillService.getAllSkills(request);
|
|
110
51
|
return {
|
|
111
52
|
success: true,
|
|
112
53
|
message: "Successfully retrieved skill list",
|
|
113
|
-
data: {
|
|
114
|
-
records: serializedSkills,
|
|
115
|
-
total: serializedSkills.length,
|
|
116
|
-
},
|
|
54
|
+
data: { records: skills.map(serializeSkill), total: skills.length },
|
|
117
55
|
};
|
|
118
56
|
} catch (error: any) {
|
|
119
57
|
return reply.status(500).send({
|
|
120
58
|
success: false,
|
|
121
59
|
message: `Failed to retrieve skills: ${error.message}`,
|
|
122
|
-
data: {
|
|
123
|
-
records: [],
|
|
124
|
-
total: 0,
|
|
125
|
-
},
|
|
60
|
+
data: { records: [], total: 0 },
|
|
126
61
|
});
|
|
127
62
|
}
|
|
128
63
|
}
|
|
129
64
|
|
|
130
|
-
/**
|
|
131
|
-
* Get a single skill by ID
|
|
132
|
-
*/
|
|
133
65
|
export async function getSkill(
|
|
134
66
|
request: FastifyRequest<{ Params: { id: string } }>,
|
|
135
67
|
reply: FastifyReply
|
|
136
68
|
): Promise<SkillResponse> {
|
|
137
69
|
try {
|
|
138
|
-
const tenantId = getTenantId(request);
|
|
139
70
|
const { id } = request.params;
|
|
140
|
-
|
|
141
|
-
const storeLattice = getStoreLattice("default", "skill");
|
|
142
|
-
const skillStore = storeLattice.store;
|
|
143
|
-
const skill = await skillStore.getSkillById(tenantId, id);
|
|
71
|
+
const skill = await skillService.getSkillById(request, id);
|
|
144
72
|
|
|
145
73
|
if (!skill) {
|
|
146
|
-
return reply.status(404).send({
|
|
147
|
-
success: false,
|
|
148
|
-
message: "Skill not found",
|
|
149
|
-
});
|
|
74
|
+
return reply.status(404).send({ success: false, message: "Skill not found" });
|
|
150
75
|
}
|
|
151
76
|
|
|
152
|
-
return {
|
|
153
|
-
success: true,
|
|
154
|
-
message: "Successfully retrieved skill",
|
|
155
|
-
data: serializeSkill(skill),
|
|
156
|
-
};
|
|
77
|
+
return { success: true, message: "Successfully retrieved skill", data: serializeSkill(skill) };
|
|
157
78
|
} catch (error: any) {
|
|
158
|
-
return reply.status(500).send({
|
|
159
|
-
success: false,
|
|
160
|
-
message: `Failed to retrieve skill: ${error.message}`,
|
|
161
|
-
});
|
|
79
|
+
return reply.status(500).send({ success: false, message: `Failed to retrieve skill: ${error.message}` });
|
|
162
80
|
}
|
|
163
81
|
}
|
|
164
82
|
|
|
165
|
-
/**
|
|
166
|
-
* Create a new skill
|
|
167
|
-
*/
|
|
168
83
|
export async function createSkill(
|
|
169
84
|
request: FastifyRequest<{ Body: CreateSkillRequest }>,
|
|
170
85
|
reply: FastifyReply
|
|
171
86
|
): Promise<SkillResponse> {
|
|
172
87
|
try {
|
|
173
88
|
const data = request.body;
|
|
174
|
-
|
|
175
|
-
// Validate required fields
|
|
176
89
|
if (!data.name) {
|
|
177
|
-
return reply.status(400).send({
|
|
178
|
-
success: false,
|
|
179
|
-
message: "name is required",
|
|
180
|
-
});
|
|
90
|
+
return reply.status(400).send({ success: false, message: "name is required" });
|
|
181
91
|
}
|
|
182
|
-
|
|
183
92
|
if (!data.description) {
|
|
184
|
-
return reply.status(400).send({
|
|
185
|
-
success: false,
|
|
186
|
-
message: "description is required",
|
|
187
|
-
});
|
|
93
|
+
return reply.status(400).send({ success: false, message: "description is required" });
|
|
188
94
|
}
|
|
189
95
|
|
|
190
|
-
// Validate name format
|
|
191
|
-
try {
|
|
192
|
-
validateSkillName(data.name);
|
|
193
|
-
} catch (error: any) {
|
|
194
|
-
return reply.status(400).send({
|
|
195
|
-
success: false,
|
|
196
|
-
message: error.message || "Invalid skill name format",
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// ID must equal name (name is used for path addressing)
|
|
201
96
|
const id = (request.body as any).id || data.name;
|
|
202
|
-
|
|
203
97
|
if (id !== data.name) {
|
|
204
98
|
return reply.status(400).send({
|
|
205
99
|
success: false,
|
|
206
|
-
message: `id "${id}" must equal name "${data.name}"
|
|
100
|
+
message: `id "${id}" must equal name "${data.name}"`,
|
|
207
101
|
});
|
|
208
102
|
}
|
|
209
103
|
|
|
210
|
-
const
|
|
211
|
-
const storeLattice = getStoreLattice("default", "skill");
|
|
212
|
-
const skillStore = storeLattice.store;
|
|
213
|
-
|
|
214
|
-
// Check if skill already exists
|
|
215
|
-
const exists = await skillStore.hasSkill(tenantId, id);
|
|
216
|
-
if (exists) {
|
|
217
|
-
return reply.status(409).send({
|
|
218
|
-
success: false,
|
|
219
|
-
message: `Skill with id "${id}" already exists`,
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Create skill
|
|
224
|
-
const newSkill = await skillStore.createSkill(tenantId, id, data);
|
|
225
|
-
|
|
104
|
+
const skill = await skillService.createSkill(request, id, data);
|
|
226
105
|
return reply.status(201).send({
|
|
227
106
|
success: true,
|
|
228
107
|
message: "Successfully created skill",
|
|
229
|
-
data: serializeSkill(
|
|
108
|
+
data: serializeSkill(skill),
|
|
230
109
|
});
|
|
231
110
|
} catch (error: any) {
|
|
232
|
-
|
|
233
|
-
success: false,
|
|
234
|
-
|
|
235
|
-
|
|
111
|
+
if (error.message?.includes("already exists")) {
|
|
112
|
+
return reply.status(409).send({ success: false, message: error.message });
|
|
113
|
+
}
|
|
114
|
+
if (error.message?.includes("must equal name") || error.message?.includes("Invalid skill name")) {
|
|
115
|
+
return reply.status(400).send({ success: false, message: error.message });
|
|
116
|
+
}
|
|
117
|
+
return reply.status(500).send({ success: false, message: `Failed to create skill: ${error.message}` });
|
|
236
118
|
}
|
|
237
119
|
}
|
|
238
120
|
|
|
239
|
-
/**
|
|
240
|
-
* Update an existing skill by ID
|
|
241
|
-
*/
|
|
242
121
|
export async function updateSkill(
|
|
243
|
-
request: FastifyRequest<{
|
|
244
|
-
Params: { id: string };
|
|
245
|
-
Body: SkillUpdateBody;
|
|
246
|
-
}>,
|
|
122
|
+
request: FastifyRequest<{ Params: { id: string }; Body: SkillUpdateBody }>,
|
|
247
123
|
reply: FastifyReply
|
|
248
124
|
): Promise<SkillResponse> {
|
|
249
125
|
try {
|
|
250
126
|
const { id } = request.params;
|
|
251
127
|
const updates = request.body;
|
|
252
128
|
|
|
253
|
-
|
|
254
|
-
if (updates.name !== undefined) {
|
|
255
|
-
try {
|
|
256
|
-
validateSkillName(updates.name);
|
|
257
|
-
} catch (error: any) {
|
|
258
|
-
return reply.status(400).send({
|
|
259
|
-
success: false,
|
|
260
|
-
message: error.message || "Invalid skill name format",
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const tenantId = getTenantId(request);
|
|
266
|
-
const storeLattice = getStoreLattice("default", "skill");
|
|
267
|
-
const skillStore = storeLattice.store;
|
|
268
|
-
|
|
269
|
-
// Check if skill exists
|
|
270
|
-
const exists = await skillStore.hasSkill(tenantId, id);
|
|
271
|
-
if (!exists) {
|
|
272
|
-
return reply.status(404).send({
|
|
273
|
-
success: false,
|
|
274
|
-
message: "Skill not found",
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Update skill
|
|
279
|
-
const updatedSkill = await skillStore.updateSkill(tenantId, id, updates);
|
|
129
|
+
const skill = await skillService.updateSkill(request, id, updates);
|
|
280
130
|
|
|
281
|
-
if (!
|
|
282
|
-
return reply.status(
|
|
283
|
-
success: false,
|
|
284
|
-
message: "Failed to update skill",
|
|
285
|
-
});
|
|
131
|
+
if (!skill) {
|
|
132
|
+
return reply.status(404).send({ success: false, message: "Skill not found" });
|
|
286
133
|
}
|
|
287
134
|
|
|
288
|
-
return {
|
|
289
|
-
success: true,
|
|
290
|
-
message: "Successfully updated skill",
|
|
291
|
-
data: serializeSkill(updatedSkill),
|
|
292
|
-
};
|
|
135
|
+
return { success: true, message: "Successfully updated skill", data: serializeSkill(skill) };
|
|
293
136
|
} catch (error: any) {
|
|
294
|
-
|
|
295
|
-
success: false,
|
|
296
|
-
|
|
297
|
-
});
|
|
137
|
+
if (error.message?.includes("Invalid skill name")) {
|
|
138
|
+
return reply.status(400).send({ success: false, message: error.message });
|
|
139
|
+
}
|
|
140
|
+
return reply.status(500).send({ success: false, message: `Failed to update skill: ${error.message}` });
|
|
298
141
|
}
|
|
299
142
|
}
|
|
300
143
|
|
|
301
|
-
/**
|
|
302
|
-
* Delete a skill by ID
|
|
303
|
-
*/
|
|
304
144
|
export async function deleteSkill(
|
|
305
145
|
request: FastifyRequest<{ Params: { id: string } }>,
|
|
306
146
|
reply: FastifyReply
|
|
307
147
|
): Promise<{ success: boolean; message: string }> {
|
|
308
148
|
try {
|
|
309
149
|
const { id } = request.params;
|
|
150
|
+
const result = await skillService.deleteSkill(request, id);
|
|
310
151
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const skillStore = storeLattice.store;
|
|
314
|
-
|
|
315
|
-
// Check if skill exists
|
|
316
|
-
const exists = await skillStore.hasSkill(tenantId, id);
|
|
317
|
-
if (!exists) {
|
|
318
|
-
return reply.status(404).send({
|
|
319
|
-
success: false,
|
|
320
|
-
message: "Skill not found",
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Delete the skill
|
|
325
|
-
const deleted = await skillStore.deleteSkill(tenantId, id);
|
|
326
|
-
|
|
327
|
-
if (!deleted) {
|
|
328
|
-
return reply.status(500).send({
|
|
329
|
-
success: false,
|
|
330
|
-
message: "Failed to delete skill",
|
|
331
|
-
});
|
|
152
|
+
if (!result) {
|
|
153
|
+
return reply.status(404).send({ success: false, message: "Skill not found" });
|
|
332
154
|
}
|
|
333
155
|
|
|
334
|
-
return {
|
|
335
|
-
success: true,
|
|
336
|
-
message: "Successfully deleted skill",
|
|
337
|
-
};
|
|
156
|
+
return { success: true, message: "Successfully deleted skill" };
|
|
338
157
|
} catch (error: any) {
|
|
339
|
-
return reply.status(500).send({
|
|
340
|
-
success: false,
|
|
341
|
-
message: `Failed to delete skill: ${error.message}`,
|
|
342
|
-
});
|
|
158
|
+
return reply.status(500).send({ success: false, message: `Failed to delete skill: ${error.message}` });
|
|
343
159
|
}
|
|
344
160
|
}
|
|
345
161
|
|
|
346
|
-
/**
|
|
347
|
-
* Search skills by metadata
|
|
348
|
-
*/
|
|
349
162
|
export async function searchSkillsByMetadata(
|
|
350
|
-
request: FastifyRequest<{
|
|
351
|
-
Querystring: { key: string; value: string };
|
|
352
|
-
}>,
|
|
163
|
+
request: FastifyRequest<{ Querystring: { key: string; value: string } }>,
|
|
353
164
|
reply: FastifyReply
|
|
354
165
|
): Promise<SkillListResponse> {
|
|
355
166
|
try {
|
|
356
167
|
const { key, value } = request.query;
|
|
357
|
-
|
|
358
168
|
if (!key || !value) {
|
|
359
169
|
return reply.status(400).send({
|
|
360
170
|
success: false,
|
|
361
171
|
message: "key and value query parameters are required",
|
|
362
|
-
data: {
|
|
363
|
-
records: [],
|
|
364
|
-
total: 0,
|
|
365
|
-
},
|
|
172
|
+
data: { records: [], total: 0 },
|
|
366
173
|
});
|
|
367
174
|
}
|
|
368
175
|
|
|
369
|
-
const
|
|
370
|
-
const storeLattice = getStoreLattice("default", "skill");
|
|
371
|
-
const skillStore = storeLattice.store;
|
|
372
|
-
const skills = await skillStore.searchByMetadata(tenantId, key, value);
|
|
373
|
-
|
|
374
|
-
// Serialize skills to convert Date objects to ISO strings
|
|
375
|
-
const serializedSkills = skills.map(serializeSkill);
|
|
376
|
-
|
|
176
|
+
const skills = await skillService.searchByMetadata(request, key, value);
|
|
377
177
|
return {
|
|
378
178
|
success: true,
|
|
379
179
|
message: "Successfully searched skills",
|
|
380
|
-
data: {
|
|
381
|
-
records: serializedSkills,
|
|
382
|
-
total: serializedSkills.length,
|
|
383
|
-
},
|
|
180
|
+
data: { records: skills.map(serializeSkill), total: skills.length },
|
|
384
181
|
};
|
|
385
182
|
} catch (error: any) {
|
|
386
183
|
return reply.status(500).send({
|
|
387
184
|
success: false,
|
|
388
185
|
message: `Failed to search skills: ${error.message}`,
|
|
389
|
-
data: {
|
|
390
|
-
records: [],
|
|
391
|
-
total: 0,
|
|
392
|
-
},
|
|
186
|
+
data: { records: [], total: 0 },
|
|
393
187
|
});
|
|
394
188
|
}
|
|
395
189
|
}
|
|
396
190
|
|
|
397
|
-
/**
|
|
398
|
-
* Filter skills by compatibility
|
|
399
|
-
*/
|
|
400
191
|
export async function filterSkillsByCompatibility(
|
|
401
|
-
request: FastifyRequest<{
|
|
402
|
-
Querystring: { compatibility: string };
|
|
403
|
-
}>,
|
|
192
|
+
request: FastifyRequest<{ Querystring: { compatibility: string } }>,
|
|
404
193
|
reply: FastifyReply
|
|
405
194
|
): Promise<SkillListResponse> {
|
|
406
195
|
try {
|
|
407
196
|
const { compatibility } = request.query;
|
|
408
|
-
|
|
409
197
|
if (!compatibility) {
|
|
410
198
|
return reply.status(400).send({
|
|
411
199
|
success: false,
|
|
412
200
|
message: "compatibility query parameter is required",
|
|
413
|
-
data: {
|
|
414
|
-
records: [],
|
|
415
|
-
total: 0,
|
|
416
|
-
},
|
|
201
|
+
data: { records: [], total: 0 },
|
|
417
202
|
});
|
|
418
203
|
}
|
|
419
204
|
|
|
420
|
-
const
|
|
421
|
-
const storeLattice = getStoreLattice("default", "skill");
|
|
422
|
-
const skillStore = storeLattice.store;
|
|
423
|
-
const skills = await skillStore.filterByCompatibility(tenantId, compatibility);
|
|
424
|
-
|
|
425
|
-
// Serialize skills to convert Date objects to ISO strings
|
|
426
|
-
const serializedSkills = skills.map(serializeSkill);
|
|
427
|
-
|
|
205
|
+
const skills = await skillService.filterByCompatibility(request, compatibility);
|
|
428
206
|
return {
|
|
429
207
|
success: true,
|
|
430
208
|
message: "Successfully filtered skills",
|
|
431
|
-
data: {
|
|
432
|
-
records: serializedSkills,
|
|
433
|
-
total: serializedSkills.length,
|
|
434
|
-
},
|
|
209
|
+
data: { records: skills.map(serializeSkill), total: skills.length },
|
|
435
210
|
};
|
|
436
211
|
} catch (error: any) {
|
|
437
212
|
return reply.status(500).send({
|
|
438
213
|
success: false,
|
|
439
214
|
message: `Failed to filter skills: ${error.message}`,
|
|
440
|
-
data: {
|
|
441
|
-
records: [],
|
|
442
|
-
total: 0,
|
|
443
|
-
},
|
|
215
|
+
data: { records: [], total: 0 },
|
|
444
216
|
});
|
|
445
217
|
}
|
|
446
218
|
}
|
|
447
219
|
|
|
448
|
-
/**
|
|
449
|
-
* Filter skills by license
|
|
450
|
-
*/
|
|
451
220
|
export async function filterSkillsByLicense(
|
|
452
|
-
request: FastifyRequest<{
|
|
453
|
-
Querystring: { license: string };
|
|
454
|
-
}>,
|
|
221
|
+
request: FastifyRequest<{ Querystring: { license: string } }>,
|
|
455
222
|
reply: FastifyReply
|
|
456
223
|
): Promise<SkillListResponse> {
|
|
457
224
|
try {
|
|
458
225
|
const { license } = request.query;
|
|
459
|
-
|
|
460
226
|
if (!license) {
|
|
461
227
|
return reply.status(400).send({
|
|
462
228
|
success: false,
|
|
463
229
|
message: "license query parameter is required",
|
|
464
|
-
data: {
|
|
465
|
-
records: [],
|
|
466
|
-
total: 0,
|
|
467
|
-
},
|
|
230
|
+
data: { records: [], total: 0 },
|
|
468
231
|
});
|
|
469
232
|
}
|
|
470
233
|
|
|
471
|
-
const
|
|
472
|
-
const storeLattice = getStoreLattice("default", "skill");
|
|
473
|
-
const skillStore = storeLattice.store;
|
|
474
|
-
const skills = await skillStore.filterByLicense(tenantId, license);
|
|
475
|
-
|
|
476
|
-
// Serialize skills to convert Date objects to ISO strings
|
|
477
|
-
const serializedSkills = skills.map(serializeSkill);
|
|
478
|
-
|
|
234
|
+
const skills = await skillService.filterByLicense(request, license);
|
|
479
235
|
return {
|
|
480
236
|
success: true,
|
|
481
237
|
message: "Successfully filtered skills",
|
|
482
|
-
data: {
|
|
483
|
-
records: serializedSkills,
|
|
484
|
-
total: serializedSkills.length,
|
|
485
|
-
},
|
|
238
|
+
data: { records: skills.map(serializeSkill), total: skills.length },
|
|
486
239
|
};
|
|
487
240
|
} catch (error: any) {
|
|
488
241
|
return reply.status(500).send({
|
|
489
242
|
success: false,
|
|
490
243
|
message: `Failed to filter skills: ${error.message}`,
|
|
491
|
-
data: {
|
|
492
|
-
records: [],
|
|
493
|
-
total: 0,
|
|
494
|
-
},
|
|
244
|
+
data: { records: [], total: 0 },
|
|
495
245
|
});
|
|
496
246
|
}
|
|
497
247
|
}
|
|
@@ -58,20 +58,22 @@ interface ThreadUpdateBody {
|
|
|
58
58
|
export async function getThreadList(
|
|
59
59
|
request: FastifyRequest<{
|
|
60
60
|
Params: { assistantId: string };
|
|
61
|
-
Querystring: { workspaceId?: string; projectId?: string };
|
|
62
61
|
}>,
|
|
63
62
|
reply: FastifyReply
|
|
64
63
|
): Promise<ThreadListResponse> {
|
|
65
64
|
const tenantId = getTenantId(request);
|
|
66
65
|
const { assistantId } = request.params;
|
|
67
66
|
|
|
68
|
-
// Build metadata filter from
|
|
67
|
+
// Build metadata filter from headers (workspace/project isolation)
|
|
69
68
|
const metadataFilter: Record<string, string> = {};
|
|
70
|
-
|
|
71
|
-
|
|
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;
|
|
72
74
|
}
|
|
73
|
-
if (
|
|
74
|
-
metadataFilter.projectId =
|
|
75
|
+
if (projectId) {
|
|
76
|
+
metadataFilter.projectId = projectId;
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
const storeLattice = getStoreLattice("default", "thread");
|