@axiom-lattice/gateway 2.1.20 → 2.1.22
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 +20 -0
- package/dist/index.js +691 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +680 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -4
- package/src/controllers/sandbox.ts +150 -0
- package/src/controllers/skills.ts +474 -0
- package/src/controllers/tools.ts +410 -0
- package/src/index.ts +4 -0
- package/src/routes/index.ts +69 -1
- package/src/schemas/index.ts +495 -0
- package/src/services/agent_service.ts +14 -6
- package/src/services/sandbox_service.ts +222 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import { FastifyRequest, FastifyReply } from "fastify";
|
|
2
|
+
import { getStoreLattice, toolLatticeManager } from "@axiom-lattice/core";
|
|
3
|
+
import type {
|
|
4
|
+
Tool,
|
|
5
|
+
ToolConfig,
|
|
6
|
+
} from "@axiom-lattice/protocols";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Tools Controller
|
|
10
|
+
* Handles tool-related CRUD operations
|
|
11
|
+
*/
|
|
12
|
+
|
|
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
|
+
/**
|
|
284
|
+
* Tool config meta response interface
|
|
285
|
+
*/
|
|
286
|
+
interface ToolConfigMetaResponse {
|
|
287
|
+
success: boolean;
|
|
288
|
+
message: string;
|
|
289
|
+
data: {
|
|
290
|
+
records: Array<{
|
|
291
|
+
id: string;
|
|
292
|
+
name: string;
|
|
293
|
+
description: string;
|
|
294
|
+
schema?: any; // Serialized schema
|
|
295
|
+
returnDirect?: boolean;
|
|
296
|
+
needUserApprove?: boolean;
|
|
297
|
+
}>;
|
|
298
|
+
total: number;
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Serialize ZodSchema to JSON-serializable format
|
|
304
|
+
* Attempts to extract schema information for API response
|
|
305
|
+
*/
|
|
306
|
+
function serializeSchema(schema: any): any {
|
|
307
|
+
if (!schema) {
|
|
308
|
+
return undefined;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
try {
|
|
312
|
+
// Try to get JSON schema if available (zod-to-json-schema or similar)
|
|
313
|
+
if (schema._def) {
|
|
314
|
+
// For Zod schemas, try to extract basic info
|
|
315
|
+
const def = schema._def;
|
|
316
|
+
if (def.typeName === "ZodObject") {
|
|
317
|
+
// Extract shape information
|
|
318
|
+
const shape = def.shape();
|
|
319
|
+
const properties: Record<string, any> = {};
|
|
320
|
+
const required: string[] = [];
|
|
321
|
+
|
|
322
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
323
|
+
const fieldDef = (value as any)._def;
|
|
324
|
+
if (fieldDef) {
|
|
325
|
+
properties[key] = {
|
|
326
|
+
type: fieldDef.typeName === "ZodString" ? "string" :
|
|
327
|
+
fieldDef.typeName === "ZodNumber" ? "number" :
|
|
328
|
+
fieldDef.typeName === "ZodBoolean" ? "boolean" :
|
|
329
|
+
fieldDef.typeName === "ZodArray" ? "array" :
|
|
330
|
+
fieldDef.typeName === "ZodObject" ? "object" : "unknown",
|
|
331
|
+
description: fieldDef.description,
|
|
332
|
+
};
|
|
333
|
+
if (!(value as any).isOptional()) {
|
|
334
|
+
required.push(key);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return {
|
|
340
|
+
type: "object",
|
|
341
|
+
properties,
|
|
342
|
+
required: required.length > 0 ? required : undefined,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Fallback: return schema description or type name
|
|
348
|
+
return {
|
|
349
|
+
type: "object",
|
|
350
|
+
description: schema.description || "Schema definition",
|
|
351
|
+
};
|
|
352
|
+
} catch (error) {
|
|
353
|
+
// If serialization fails, return a safe fallback
|
|
354
|
+
return {
|
|
355
|
+
type: "object",
|
|
356
|
+
description: "Schema definition",
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Get tool config meta from ToolLatticeManager
|
|
363
|
+
* Exposes tool configuration metadata via /api/tools endpoint
|
|
364
|
+
*/
|
|
365
|
+
export async function getToolConfigs(
|
|
366
|
+
request: FastifyRequest,
|
|
367
|
+
reply: FastifyReply
|
|
368
|
+
): Promise<ToolConfigMetaResponse> {
|
|
369
|
+
try {
|
|
370
|
+
const allLattices = toolLatticeManager.getAllLattices();
|
|
371
|
+
|
|
372
|
+
const toolConfigs = allLattices.map((lattice) => {
|
|
373
|
+
const config = { ...lattice.config };
|
|
374
|
+
|
|
375
|
+
// Serialize schema if present
|
|
376
|
+
const serializedSchema = config.schema ? serializeSchema(config.schema) : undefined;
|
|
377
|
+
|
|
378
|
+
return {
|
|
379
|
+
id: lattice.key,
|
|
380
|
+
name: config.name,
|
|
381
|
+
description: config.description,
|
|
382
|
+
schema: serializedSchema,
|
|
383
|
+
returnDirect: config.returnDirect,
|
|
384
|
+
needUserApprove: config.needUserApprove,
|
|
385
|
+
};
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
return reply.send({
|
|
389
|
+
success: true,
|
|
390
|
+
message: "Successfully retrieved tool configs",
|
|
391
|
+
data: {
|
|
392
|
+
records: toolConfigs,
|
|
393
|
+
total: toolConfigs.length,
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
} catch (error: any) {
|
|
397
|
+
console.error("Failed to get tool configs", {
|
|
398
|
+
error: error.message,
|
|
399
|
+
stack: error.stack,
|
|
400
|
+
});
|
|
401
|
+
return reply.status(500).send({
|
|
402
|
+
success: false,
|
|
403
|
+
message: `Failed to retrieve tool configs: ${error.message}`,
|
|
404
|
+
data: {
|
|
405
|
+
records: [],
|
|
406
|
+
total: 0,
|
|
407
|
+
},
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fastify from "fastify";
|
|
2
2
|
import cors from "@fastify/cors";
|
|
3
3
|
import sensible from "@fastify/sensible";
|
|
4
|
+
import websocket from "@fastify/websocket";
|
|
4
5
|
import { registerLatticeRoutes } from "./routes";
|
|
5
6
|
import { configureSwagger } from "./swagger";
|
|
6
7
|
import {
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
PinoFileOptions,
|
|
20
21
|
} from "@axiom-lattice/protocols";
|
|
21
22
|
|
|
23
|
+
|
|
22
24
|
process.on("unhandledRejection", (reason, promise) => {
|
|
23
25
|
console.error("未处理的Promise拒绝:", reason);
|
|
24
26
|
// 可以在这里进行日志记录或其他处理
|
|
@@ -59,6 +61,7 @@ const app = fastify({
|
|
|
59
61
|
bodyLimit: Number(process.env.BODY_LIMIT) || 50 * 1024 * 1024, // Default 50MB, configurable via BODY_LIMIT env var
|
|
60
62
|
});
|
|
61
63
|
|
|
64
|
+
|
|
62
65
|
// Add custom logging hooks
|
|
63
66
|
app.addHook("onRequest", (request, reply, done) => {
|
|
64
67
|
// Convert headers to strings (Fastify headers can be string | string[])
|
|
@@ -116,6 +119,7 @@ app.register(cors, {
|
|
|
116
119
|
credentials: true,
|
|
117
120
|
});
|
|
118
121
|
app.register(sensible);
|
|
122
|
+
app.register(websocket);
|
|
119
123
|
|
|
120
124
|
// Error handler
|
|
121
125
|
app.setErrorHandler((error, request, reply) => {
|
package/src/routes/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FastifyInstance } from "fastify";
|
|
2
|
+
import { ScheduledTaskStatus } from "@axiom-lattice/protocols";
|
|
2
3
|
import * as assistantController from "../controllers/assistant";
|
|
3
4
|
import * as runController from "../controllers/run";
|
|
4
5
|
import * as memoryController from "../controllers/memory";
|
|
@@ -9,6 +10,8 @@ import * as schedulesController from "../controllers/schedules";
|
|
|
9
10
|
import * as configController from "../controllers/config";
|
|
10
11
|
import * as modelsController from "../controllers/models";
|
|
11
12
|
import * as healthController from "../controllers/health";
|
|
13
|
+
import * as skillsController from "../controllers/skills";
|
|
14
|
+
import * as toolsController from "../controllers/tools";
|
|
12
15
|
import {
|
|
13
16
|
createRunSchema,
|
|
14
17
|
getAllMemoryItemsSchema,
|
|
@@ -23,7 +26,9 @@ import {
|
|
|
23
26
|
updateConfigSchema,
|
|
24
27
|
getConfigSchema,
|
|
25
28
|
getHealthSchema,
|
|
29
|
+
getSandboxUrlSchema,
|
|
26
30
|
} from "../schemas";
|
|
31
|
+
import { registerSandboxProxyRoutes } from "../controllers/sandbox";
|
|
27
32
|
|
|
28
33
|
export const registerLatticeRoutes = (app: FastifyInstance): void => {
|
|
29
34
|
// 运行路由
|
|
@@ -190,6 +195,9 @@ export const registerLatticeRoutes = (app: FastifyInstance): void => {
|
|
|
190
195
|
Body: { models: any[] };
|
|
191
196
|
}>("/api/models", modelsController.updateModels);
|
|
192
197
|
|
|
198
|
+
// Tools config meta route
|
|
199
|
+
app.get("/api/tools", toolsController.getToolConfigs);
|
|
200
|
+
|
|
193
201
|
// Health check route
|
|
194
202
|
app.get(
|
|
195
203
|
"/health",
|
|
@@ -200,7 +208,11 @@ export const registerLatticeRoutes = (app: FastifyInstance): void => {
|
|
|
200
208
|
// Schedule routes for viewing scheduled tasks by thread
|
|
201
209
|
app.get<{
|
|
202
210
|
Params: { assistantId: string; threadId: string };
|
|
203
|
-
Querystring: {
|
|
211
|
+
Querystring: {
|
|
212
|
+
status?: ScheduledTaskStatus;
|
|
213
|
+
limit?: string;
|
|
214
|
+
offset?: string;
|
|
215
|
+
};
|
|
204
216
|
}>(
|
|
205
217
|
"/api/assistants/:assistantId/threads/:threadId/schedules",
|
|
206
218
|
schedulesController.getThreadSchedules
|
|
@@ -225,4 +237,60 @@ export const registerLatticeRoutes = (app: FastifyInstance): void => {
|
|
|
225
237
|
app.post<{
|
|
226
238
|
Params: { taskId: string };
|
|
227
239
|
}>("/api/schedules/:taskId/resume", schedulesController.resumeScheduledTask);
|
|
240
|
+
|
|
241
|
+
// Skills CRUD routes
|
|
242
|
+
app.get("/api/skills", skillsController.getSkillList);
|
|
243
|
+
|
|
244
|
+
app.get<{
|
|
245
|
+
Params: { id: string };
|
|
246
|
+
}>(
|
|
247
|
+
"/api/skills/:id",
|
|
248
|
+
skillsController.getSkill
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
app.post<{
|
|
252
|
+
Body: any;
|
|
253
|
+
}>(
|
|
254
|
+
"/api/skills",
|
|
255
|
+
skillsController.createSkill
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
app.put<{
|
|
259
|
+
Params: { id: string };
|
|
260
|
+
Body: any;
|
|
261
|
+
}>(
|
|
262
|
+
"/api/skills/:id",
|
|
263
|
+
skillsController.updateSkill
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
app.delete<{
|
|
267
|
+
Params: { id: string };
|
|
268
|
+
}>(
|
|
269
|
+
"/api/skills/:id",
|
|
270
|
+
skillsController.deleteSkill
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
// Skills search and filter routes
|
|
274
|
+
app.get<{
|
|
275
|
+
Querystring: { key: string; value: string };
|
|
276
|
+
}>(
|
|
277
|
+
"/api/skills/search/metadata",
|
|
278
|
+
skillsController.searchSkillsByMetadata
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
app.get<{
|
|
282
|
+
Querystring: { compatibility: string };
|
|
283
|
+
}>(
|
|
284
|
+
"/api/skills/filter/compatibility",
|
|
285
|
+
skillsController.filterSkillsByCompatibility
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
app.get<{
|
|
289
|
+
Querystring: { license: string };
|
|
290
|
+
}>(
|
|
291
|
+
"/api/skills/filter/license",
|
|
292
|
+
skillsController.filterSkillsByLicense
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
registerSandboxProxyRoutes(app);
|
|
228
296
|
};
|