@axiom-lattice/gateway 2.1.11 → 2.1.13
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 +16 -0
- package/README.md +53 -0
- package/dist/index.js +798 -68
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +794 -64
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/config.ts +124 -0
- package/src/controllers/assistant.ts +274 -3
- package/src/controllers/config.ts +126 -0
- package/src/controllers/models.ts +152 -0
- package/src/controllers/threads.ts +189 -0
- package/src/routes/index.ts +80 -1
- package/src/schemas/index.ts +74 -0
- package/src/services/supabase.ts +44 -10
- package/src/stores/assistant_store.ts +82 -0
- package/src/stores/thread_store.ts +115 -0
- package/src/types/index.ts +14 -0
package/dist/index.mjs
CHANGED
|
@@ -223,6 +223,226 @@ async function resume_stream({
|
|
|
223
223
|
};
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
// src/stores/assistant_store.ts
|
|
227
|
+
var AssistantStore = class {
|
|
228
|
+
constructor() {
|
|
229
|
+
this.assistants = /* @__PURE__ */ new Map();
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get all assistants
|
|
233
|
+
*/
|
|
234
|
+
getAllAssistants() {
|
|
235
|
+
return Array.from(this.assistants.values());
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Get assistant by ID
|
|
239
|
+
*/
|
|
240
|
+
getAssistantById(id) {
|
|
241
|
+
return this.assistants.get(id);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Create a new assistant
|
|
245
|
+
*/
|
|
246
|
+
createAssistant(id, data) {
|
|
247
|
+
const now = /* @__PURE__ */ new Date();
|
|
248
|
+
const assistant = {
|
|
249
|
+
id,
|
|
250
|
+
name: data.name,
|
|
251
|
+
description: data.description,
|
|
252
|
+
graphDefinition: data.graphDefinition,
|
|
253
|
+
createdAt: now,
|
|
254
|
+
updatedAt: now
|
|
255
|
+
};
|
|
256
|
+
this.assistants.set(id, assistant);
|
|
257
|
+
return assistant;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Update an existing assistant
|
|
261
|
+
*/
|
|
262
|
+
updateAssistant(id, updates) {
|
|
263
|
+
const existing = this.assistants.get(id);
|
|
264
|
+
if (!existing) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
const updated = {
|
|
268
|
+
...existing,
|
|
269
|
+
...updates,
|
|
270
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
271
|
+
};
|
|
272
|
+
this.assistants.set(id, updated);
|
|
273
|
+
return updated;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Delete an assistant by ID
|
|
277
|
+
*/
|
|
278
|
+
deleteAssistant(id) {
|
|
279
|
+
return this.assistants.delete(id);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Check if assistant exists
|
|
283
|
+
*/
|
|
284
|
+
hasAssistant(id) {
|
|
285
|
+
return this.assistants.has(id);
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
var assistantStore = new AssistantStore();
|
|
289
|
+
|
|
290
|
+
// src/controllers/assistant.ts
|
|
291
|
+
import { randomUUID } from "crypto";
|
|
292
|
+
import { getAllAgentConfigs } from "@axiom-lattice/core";
|
|
293
|
+
function convertAgentConfigToAssistant(config) {
|
|
294
|
+
return {
|
|
295
|
+
id: config.key,
|
|
296
|
+
name: config.name,
|
|
297
|
+
description: config.description,
|
|
298
|
+
graphDefinition: config,
|
|
299
|
+
// Store the full config as graphDefinition
|
|
300
|
+
createdAt: /* @__PURE__ */ new Date(0),
|
|
301
|
+
// Code-configured agents have no creation date
|
|
302
|
+
updatedAt: /* @__PURE__ */ new Date(0)
|
|
303
|
+
// Code-configured agents have no update date
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
async function getAssistantList(request, reply) {
|
|
307
|
+
const agentConfigs = await getAllAgentConfigs();
|
|
308
|
+
const codeConfiguredAssistants = agentConfigs.map(
|
|
309
|
+
convertAgentConfigToAssistant
|
|
310
|
+
);
|
|
311
|
+
const storedAssistants = assistantStore.getAllAssistants();
|
|
312
|
+
const assistantMap = /* @__PURE__ */ new Map();
|
|
313
|
+
codeConfiguredAssistants.forEach((assistant) => {
|
|
314
|
+
assistantMap.set(assistant.id, assistant);
|
|
315
|
+
});
|
|
316
|
+
storedAssistants.forEach((assistant) => {
|
|
317
|
+
assistantMap.set(assistant.id, assistant);
|
|
318
|
+
});
|
|
319
|
+
const allAssistants = Array.from(assistantMap.values());
|
|
320
|
+
return {
|
|
321
|
+
success: true,
|
|
322
|
+
message: "Successfully retrieved assistant list",
|
|
323
|
+
data: {
|
|
324
|
+
records: allAssistants,
|
|
325
|
+
total: allAssistants.length
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
async function getAssistant(request, reply) {
|
|
330
|
+
const { id } = request.params;
|
|
331
|
+
let assistant = assistantStore.getAssistantById(id);
|
|
332
|
+
if (!assistant) {
|
|
333
|
+
const agentConfigs = await getAllAgentConfigs();
|
|
334
|
+
const agentConfig = agentConfigs.find((config) => config.key === id);
|
|
335
|
+
if (agentConfig) {
|
|
336
|
+
assistant = convertAgentConfigToAssistant(agentConfig);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (!assistant) {
|
|
340
|
+
return reply.status(404).send({
|
|
341
|
+
success: false,
|
|
342
|
+
message: "Assistant not found"
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
return {
|
|
346
|
+
success: true,
|
|
347
|
+
message: "Successfully retrieved assistant",
|
|
348
|
+
data: assistant
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
async function createAssistant(request, reply) {
|
|
352
|
+
const data = request.body;
|
|
353
|
+
if (!data.name) {
|
|
354
|
+
return reply.status(400).send({
|
|
355
|
+
success: false,
|
|
356
|
+
message: "name is required"
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
if (!data.graphDefinition) {
|
|
360
|
+
return reply.status(400).send({
|
|
361
|
+
success: false,
|
|
362
|
+
message: "graphDefinition is required"
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
const id = randomUUID();
|
|
366
|
+
const newAssistant = assistantStore.createAssistant(id, data);
|
|
367
|
+
return reply.status(201).send({
|
|
368
|
+
success: true,
|
|
369
|
+
message: "Successfully created assistant",
|
|
370
|
+
data: newAssistant
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
async function updateAssistant(request, reply) {
|
|
374
|
+
const { id } = request.params;
|
|
375
|
+
const updates = request.body;
|
|
376
|
+
const agentConfigs = await getAllAgentConfigs();
|
|
377
|
+
const isCodeConfigured = agentConfigs.some((config) => config.key === id);
|
|
378
|
+
if (isCodeConfigured) {
|
|
379
|
+
return reply.status(403).send({
|
|
380
|
+
success: false,
|
|
381
|
+
message: "Cannot update code-configured assistant. Only stored assistants can be updated."
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
if (!assistantStore.hasAssistant(id)) {
|
|
385
|
+
return reply.status(404).send({
|
|
386
|
+
success: false,
|
|
387
|
+
message: "Assistant not found"
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
const updatedAssistant = assistantStore.updateAssistant(id, updates);
|
|
391
|
+
if (!updatedAssistant) {
|
|
392
|
+
return reply.status(500).send({
|
|
393
|
+
success: false,
|
|
394
|
+
message: "Failed to update assistant"
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
return {
|
|
398
|
+
success: true,
|
|
399
|
+
message: "Successfully updated assistant",
|
|
400
|
+
data: updatedAssistant
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
async function deleteAssistant(request, reply) {
|
|
404
|
+
const { id } = request.params;
|
|
405
|
+
const agentConfigs = await getAllAgentConfigs();
|
|
406
|
+
const isCodeConfigured = agentConfigs.some((config) => config.key === id);
|
|
407
|
+
if (isCodeConfigured) {
|
|
408
|
+
return reply.status(403).send({
|
|
409
|
+
success: false,
|
|
410
|
+
message: "Cannot delete code-configured assistant. Only stored assistants can be deleted."
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
if (!assistantStore.hasAssistant(id)) {
|
|
414
|
+
return reply.status(404).send({
|
|
415
|
+
success: false,
|
|
416
|
+
message: "Assistant not found"
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
const deleted = assistantStore.deleteAssistant(id);
|
|
420
|
+
if (!deleted) {
|
|
421
|
+
return reply.status(500).send({
|
|
422
|
+
success: false,
|
|
423
|
+
message: "Failed to delete assistant"
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
success: true,
|
|
428
|
+
message: "Successfully deleted assistant"
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
var getAgentGraph = async (request, reply) => {
|
|
432
|
+
try {
|
|
433
|
+
const { assistantId } = request.params;
|
|
434
|
+
const imageData = await draw_graph(assistantId);
|
|
435
|
+
reply.header("Content-Type", "application/json").send({
|
|
436
|
+
image: imageData
|
|
437
|
+
});
|
|
438
|
+
} catch (error) {
|
|
439
|
+
reply.status(500).send({
|
|
440
|
+
success: false,
|
|
441
|
+
error: error.message || "Failed to get agent graph"
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
|
|
226
446
|
// src/controllers/run.ts
|
|
227
447
|
import { v4 as v42 } from "uuid";
|
|
228
448
|
var createRun = async (request, reply) => {
|
|
@@ -490,22 +710,6 @@ var clearMemory = async (request, reply) => {
|
|
|
490
710
|
}
|
|
491
711
|
};
|
|
492
712
|
|
|
493
|
-
// src/controllers/assistant.ts
|
|
494
|
-
var getAgentGraph = async (request, reply) => {
|
|
495
|
-
try {
|
|
496
|
-
const { assistantId } = request.params;
|
|
497
|
-
const imageData = await draw_graph(assistantId);
|
|
498
|
-
reply.header("Content-Type", "application/json").send({
|
|
499
|
-
image: imageData
|
|
500
|
-
});
|
|
501
|
-
} catch (error) {
|
|
502
|
-
reply.status(500).send({
|
|
503
|
-
success: false,
|
|
504
|
-
error: error.message || "\u83B7\u53D6\u4EE3\u7406\u56FE\u8868\u5931\u8D25"
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
};
|
|
508
|
-
|
|
509
713
|
// src/controllers/agent_task.ts
|
|
510
714
|
import { AgentManager } from "@axiom-lattice/core";
|
|
511
715
|
var triggerAgentTask = async (request, reply) => {
|
|
@@ -545,6 +749,478 @@ var triggerAgentTask = async (request, reply) => {
|
|
|
545
749
|
}
|
|
546
750
|
};
|
|
547
751
|
|
|
752
|
+
// src/stores/thread_store.ts
|
|
753
|
+
var ThreadStore = class {
|
|
754
|
+
constructor() {
|
|
755
|
+
// Map<assistantId, Map<threadId, Thread>>
|
|
756
|
+
this.threads = /* @__PURE__ */ new Map();
|
|
757
|
+
}
|
|
758
|
+
/**
|
|
759
|
+
* Get all threads for a specific assistant
|
|
760
|
+
*/
|
|
761
|
+
getThreadsByAssistantId(assistantId) {
|
|
762
|
+
const assistantThreads = this.threads.get(assistantId);
|
|
763
|
+
if (!assistantThreads) {
|
|
764
|
+
return [];
|
|
765
|
+
}
|
|
766
|
+
return Array.from(assistantThreads.values());
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Get a thread by ID for a specific assistant
|
|
770
|
+
*/
|
|
771
|
+
getThreadById(assistantId, threadId) {
|
|
772
|
+
const assistantThreads = this.threads.get(assistantId);
|
|
773
|
+
if (!assistantThreads) {
|
|
774
|
+
return void 0;
|
|
775
|
+
}
|
|
776
|
+
return assistantThreads.get(threadId);
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Create a new thread for an assistant
|
|
780
|
+
*/
|
|
781
|
+
createThread(assistantId, threadId, data) {
|
|
782
|
+
const now = /* @__PURE__ */ new Date();
|
|
783
|
+
const thread = {
|
|
784
|
+
id: threadId,
|
|
785
|
+
assistantId,
|
|
786
|
+
metadata: data.metadata || {},
|
|
787
|
+
createdAt: now,
|
|
788
|
+
updatedAt: now
|
|
789
|
+
};
|
|
790
|
+
if (!this.threads.has(assistantId)) {
|
|
791
|
+
this.threads.set(assistantId, /* @__PURE__ */ new Map());
|
|
792
|
+
}
|
|
793
|
+
const assistantThreads = this.threads.get(assistantId);
|
|
794
|
+
assistantThreads.set(threadId, thread);
|
|
795
|
+
return thread;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Update an existing thread
|
|
799
|
+
*/
|
|
800
|
+
updateThread(assistantId, threadId, updates) {
|
|
801
|
+
const assistantThreads = this.threads.get(assistantId);
|
|
802
|
+
if (!assistantThreads) {
|
|
803
|
+
return null;
|
|
804
|
+
}
|
|
805
|
+
const existing = assistantThreads.get(threadId);
|
|
806
|
+
if (!existing) {
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
const updated = {
|
|
810
|
+
...existing,
|
|
811
|
+
metadata: {
|
|
812
|
+
...existing.metadata,
|
|
813
|
+
...updates.metadata || {}
|
|
814
|
+
},
|
|
815
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
816
|
+
};
|
|
817
|
+
assistantThreads.set(threadId, updated);
|
|
818
|
+
return updated;
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Delete a thread by ID
|
|
822
|
+
*/
|
|
823
|
+
deleteThread(assistantId, threadId) {
|
|
824
|
+
const assistantThreads = this.threads.get(assistantId);
|
|
825
|
+
if (!assistantThreads) {
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
return assistantThreads.delete(threadId);
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Check if thread exists
|
|
832
|
+
*/
|
|
833
|
+
hasThread(assistantId, threadId) {
|
|
834
|
+
const assistantThreads = this.threads.get(assistantId);
|
|
835
|
+
if (!assistantThreads) {
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
return assistantThreads.has(threadId);
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
var threadStore = new ThreadStore();
|
|
842
|
+
|
|
843
|
+
// src/controllers/threads.ts
|
|
844
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
845
|
+
async function getThreadList(request, reply) {
|
|
846
|
+
const { assistantId } = request.params;
|
|
847
|
+
const threads = threadStore.getThreadsByAssistantId(assistantId);
|
|
848
|
+
return {
|
|
849
|
+
success: true,
|
|
850
|
+
message: "Successfully retrieved thread list",
|
|
851
|
+
data: {
|
|
852
|
+
records: threads,
|
|
853
|
+
total: threads.length
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
async function getThread(request, reply) {
|
|
858
|
+
const { assistantId, threadId } = request.params;
|
|
859
|
+
const thread = threadStore.getThreadById(assistantId, threadId);
|
|
860
|
+
if (!thread) {
|
|
861
|
+
return reply.status(404).send({
|
|
862
|
+
success: false,
|
|
863
|
+
message: "Thread not found"
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
return {
|
|
867
|
+
success: true,
|
|
868
|
+
message: "Successfully retrieved thread",
|
|
869
|
+
data: thread
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
async function createThread(request, reply) {
|
|
873
|
+
const { assistantId } = request.params;
|
|
874
|
+
const data = request.body;
|
|
875
|
+
const threadId = randomUUID2();
|
|
876
|
+
const newThread = threadStore.createThread(assistantId, threadId, data);
|
|
877
|
+
return reply.status(201).send({
|
|
878
|
+
success: true,
|
|
879
|
+
message: "Successfully created thread",
|
|
880
|
+
data: newThread
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
async function updateThread(request, reply) {
|
|
884
|
+
const { assistantId, threadId } = request.params;
|
|
885
|
+
const updates = request.body;
|
|
886
|
+
if (!threadStore.hasThread(assistantId, threadId)) {
|
|
887
|
+
return reply.status(404).send({
|
|
888
|
+
success: false,
|
|
889
|
+
message: "Thread not found"
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
const updatedThread = threadStore.updateThread(
|
|
893
|
+
assistantId,
|
|
894
|
+
threadId,
|
|
895
|
+
updates
|
|
896
|
+
);
|
|
897
|
+
if (!updatedThread) {
|
|
898
|
+
return reply.status(500).send({
|
|
899
|
+
success: false,
|
|
900
|
+
message: "Failed to update thread"
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
return {
|
|
904
|
+
success: true,
|
|
905
|
+
message: "Successfully updated thread",
|
|
906
|
+
data: updatedThread
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
async function deleteThread(request, reply) {
|
|
910
|
+
const { assistantId, threadId } = request.params;
|
|
911
|
+
if (!threadStore.hasThread(assistantId, threadId)) {
|
|
912
|
+
return reply.status(404).send({
|
|
913
|
+
success: false,
|
|
914
|
+
message: "Thread not found"
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
const deleted = threadStore.deleteThread(assistantId, threadId);
|
|
918
|
+
if (!deleted) {
|
|
919
|
+
return reply.status(500).send({
|
|
920
|
+
success: false,
|
|
921
|
+
message: "Failed to delete thread"
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
return {
|
|
925
|
+
success: true,
|
|
926
|
+
message: "Successfully deleted thread"
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// src/config.ts
|
|
931
|
+
var ConfigService = class {
|
|
932
|
+
constructor() {
|
|
933
|
+
this.config = this.loadFromEnv();
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Load configuration from environment variables
|
|
937
|
+
*/
|
|
938
|
+
loadFromEnv() {
|
|
939
|
+
return {
|
|
940
|
+
port: process.env.PORT ? Number(process.env.PORT) : void 0,
|
|
941
|
+
queueServiceType: process.env.QUEUE_SERVICE_TYPE,
|
|
942
|
+
redisUrl: process.env.REDIS_URL,
|
|
943
|
+
redisPassword: process.env.REDIS_PASSWORD,
|
|
944
|
+
queueName: process.env.QUEUE_NAME
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Update configuration from JSON object
|
|
949
|
+
* This will update both the internal config and process.env
|
|
950
|
+
*/
|
|
951
|
+
updateConfig(jsonConfig) {
|
|
952
|
+
for (const [key, value] of Object.entries(jsonConfig)) {
|
|
953
|
+
if (value !== null && value !== void 0) {
|
|
954
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
955
|
+
for (const [nestedKey, nestedValue] of Object.entries(value)) {
|
|
956
|
+
const envKey = `${key.toUpperCase()}_${nestedKey.toUpperCase()}`;
|
|
957
|
+
process.env[envKey] = String(nestedValue);
|
|
958
|
+
}
|
|
959
|
+
} else {
|
|
960
|
+
process.env[key.toUpperCase()] = String(value);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
this.config = this.loadFromEnv();
|
|
965
|
+
this.config = this.deepMerge(this.config, jsonConfig);
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Deep merge two objects
|
|
969
|
+
*/
|
|
970
|
+
deepMerge(target, source) {
|
|
971
|
+
const output = { ...target };
|
|
972
|
+
if (this.isObject(target) && this.isObject(source)) {
|
|
973
|
+
Object.keys(source).forEach((key) => {
|
|
974
|
+
if (this.isObject(source[key])) {
|
|
975
|
+
if (!(key in target)) {
|
|
976
|
+
Object.assign(output, { [key]: source[key] });
|
|
977
|
+
} else {
|
|
978
|
+
output[key] = this.deepMerge(target[key], source[key]);
|
|
979
|
+
}
|
|
980
|
+
} else {
|
|
981
|
+
Object.assign(output, { [key]: source[key] });
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
return output;
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* Check if value is a plain object
|
|
989
|
+
*/
|
|
990
|
+
isObject(item) {
|
|
991
|
+
return item && typeof item === "object" && !Array.isArray(item);
|
|
992
|
+
}
|
|
993
|
+
/**
|
|
994
|
+
* Get current configuration
|
|
995
|
+
*/
|
|
996
|
+
getConfig() {
|
|
997
|
+
return { ...this.config };
|
|
998
|
+
}
|
|
999
|
+
};
|
|
1000
|
+
var configService = new ConfigService();
|
|
1001
|
+
|
|
1002
|
+
// src/services/queue_service.ts
|
|
1003
|
+
import {
|
|
1004
|
+
queueLatticeManager,
|
|
1005
|
+
registerQueueLattice,
|
|
1006
|
+
getQueueLattice
|
|
1007
|
+
} from "@axiom-lattice/core";
|
|
1008
|
+
import { QueueType } from "@axiom-lattice/protocols";
|
|
1009
|
+
import { RedisQueueClient } from "@axiom-lattice/queue-redis";
|
|
1010
|
+
var DEFAULT_QUEUE_KEY = "default";
|
|
1011
|
+
var queueServiceType = process.env.QUEUE_SERVICE_TYPE || "memory";
|
|
1012
|
+
var setQueueServiceType = (type) => {
|
|
1013
|
+
queueServiceType = type;
|
|
1014
|
+
console.log(`Queue service type set to: ${type}`);
|
|
1015
|
+
const queueName = process.env.QUEUE_NAME || "tasks";
|
|
1016
|
+
const config = {
|
|
1017
|
+
name: "Default Queue Service",
|
|
1018
|
+
description: `Default ${type} queue service`,
|
|
1019
|
+
type: type === "redis" ? QueueType.REDIS : QueueType.MEMORY,
|
|
1020
|
+
queueName,
|
|
1021
|
+
options: type === "redis" ? {
|
|
1022
|
+
redisUrl: process.env.REDIS_URL,
|
|
1023
|
+
redisPassword: process.env.REDIS_PASSWORD
|
|
1024
|
+
} : void 0
|
|
1025
|
+
};
|
|
1026
|
+
if (queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
|
|
1027
|
+
queueLatticeManager.removeLattice(DEFAULT_QUEUE_KEY);
|
|
1028
|
+
}
|
|
1029
|
+
let client;
|
|
1030
|
+
if (type === "redis") {
|
|
1031
|
+
client = new RedisQueueClient(queueName, {
|
|
1032
|
+
redisUrl: process.env.REDIS_URL,
|
|
1033
|
+
redisPassword: process.env.REDIS_PASSWORD
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
registerQueueLattice(DEFAULT_QUEUE_KEY, config, client);
|
|
1037
|
+
};
|
|
1038
|
+
var getQueueService = () => {
|
|
1039
|
+
if (!queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
|
|
1040
|
+
setQueueServiceType(queueServiceType);
|
|
1041
|
+
}
|
|
1042
|
+
return getQueueLattice(DEFAULT_QUEUE_KEY);
|
|
1043
|
+
};
|
|
1044
|
+
var popAgentTaskFromQueue = async () => {
|
|
1045
|
+
const queue = getQueueService();
|
|
1046
|
+
const result = await queue.pop();
|
|
1047
|
+
return result;
|
|
1048
|
+
};
|
|
1049
|
+
|
|
1050
|
+
// src/controllers/config.ts
|
|
1051
|
+
async function updateConfig(request, reply) {
|
|
1052
|
+
try {
|
|
1053
|
+
const { config: jsonConfig } = request.body;
|
|
1054
|
+
if (!jsonConfig || typeof jsonConfig !== "object") {
|
|
1055
|
+
return reply.status(400).send({
|
|
1056
|
+
success: false,
|
|
1057
|
+
error: "Invalid configuration: config must be an object"
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
configService.updateConfig(jsonConfig);
|
|
1061
|
+
const warnings = [];
|
|
1062
|
+
const requiresRestart = [];
|
|
1063
|
+
if (jsonConfig.port !== void 0) {
|
|
1064
|
+
requiresRestart.push("PORT");
|
|
1065
|
+
warnings.push("Port change requires server restart to take effect");
|
|
1066
|
+
}
|
|
1067
|
+
if (jsonConfig.queueServiceType) {
|
|
1068
|
+
setQueueServiceType(jsonConfig.queueServiceType);
|
|
1069
|
+
}
|
|
1070
|
+
if ((jsonConfig.redisUrl || jsonConfig.redisPassword) && (process.env.QUEUE_SERVICE_TYPE === "redis" || jsonConfig.queueServiceType === "redis")) {
|
|
1071
|
+
const currentType = jsonConfig.queueServiceType || process.env.QUEUE_SERVICE_TYPE || "memory";
|
|
1072
|
+
if (currentType === "redis") {
|
|
1073
|
+
setQueueServiceType("redis");
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
const updatedConfig = configService.getConfig();
|
|
1077
|
+
const safeConfig = {
|
|
1078
|
+
...updatedConfig,
|
|
1079
|
+
redisPassword: updatedConfig.redisPassword ? "***" : updatedConfig.redisPassword
|
|
1080
|
+
};
|
|
1081
|
+
return reply.send({
|
|
1082
|
+
success: true,
|
|
1083
|
+
message: "Configuration updated successfully",
|
|
1084
|
+
data: safeConfig,
|
|
1085
|
+
warnings: warnings.length > 0 ? warnings : void 0,
|
|
1086
|
+
requiresRestart: requiresRestart.length > 0 ? requiresRestart : void 0
|
|
1087
|
+
});
|
|
1088
|
+
} catch (error) {
|
|
1089
|
+
console.error("Failed to update configuration", {
|
|
1090
|
+
error: error.message,
|
|
1091
|
+
stack: error.stack
|
|
1092
|
+
});
|
|
1093
|
+
return reply.status(500).send({
|
|
1094
|
+
success: false,
|
|
1095
|
+
error: error.message || "Failed to update configuration"
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
async function getConfig(request, reply) {
|
|
1100
|
+
try {
|
|
1101
|
+
const currentConfig = configService.getConfig();
|
|
1102
|
+
const safeConfig = {
|
|
1103
|
+
...currentConfig,
|
|
1104
|
+
redisPassword: currentConfig.redisPassword ? "***" : currentConfig.redisPassword
|
|
1105
|
+
};
|
|
1106
|
+
return reply.send({
|
|
1107
|
+
success: true,
|
|
1108
|
+
data: safeConfig
|
|
1109
|
+
});
|
|
1110
|
+
} catch (error) {
|
|
1111
|
+
console.error("Failed to get configuration", {
|
|
1112
|
+
error: error.message,
|
|
1113
|
+
stack: error.stack
|
|
1114
|
+
});
|
|
1115
|
+
return reply.status(500).send({
|
|
1116
|
+
success: false,
|
|
1117
|
+
error: error.message || "Failed to get configuration"
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
// src/controllers/models.ts
|
|
1123
|
+
import { registerModelLattice, modelLatticeManager } from "@axiom-lattice/core";
|
|
1124
|
+
async function getModels(request, reply) {
|
|
1125
|
+
try {
|
|
1126
|
+
const allLattices = modelLatticeManager.getAllLattices();
|
|
1127
|
+
const models = allLattices.map((lattice) => {
|
|
1128
|
+
const config = lattice.client.config || {};
|
|
1129
|
+
return {
|
|
1130
|
+
key: lattice.key,
|
|
1131
|
+
model: config.model || "",
|
|
1132
|
+
provider: config.provider || "openai",
|
|
1133
|
+
streaming: config.streaming || false,
|
|
1134
|
+
apiKey: config.apiKey || "",
|
|
1135
|
+
baseURL: config.baseURL || "",
|
|
1136
|
+
maxTokens: config.maxTokens,
|
|
1137
|
+
temperature: config.temperature,
|
|
1138
|
+
timeout: config.timeout,
|
|
1139
|
+
maxRetries: config.maxRetries
|
|
1140
|
+
};
|
|
1141
|
+
});
|
|
1142
|
+
return reply.send({
|
|
1143
|
+
success: true,
|
|
1144
|
+
data: models
|
|
1145
|
+
});
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
console.error("Failed to get models", {
|
|
1148
|
+
error: error.message,
|
|
1149
|
+
stack: error.stack
|
|
1150
|
+
});
|
|
1151
|
+
return reply.status(500).send({
|
|
1152
|
+
success: false,
|
|
1153
|
+
error: error.message || "Failed to get models"
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
async function updateModels(request, reply) {
|
|
1158
|
+
try {
|
|
1159
|
+
const { models } = request.body;
|
|
1160
|
+
if (!models || !Array.isArray(models)) {
|
|
1161
|
+
return reply.status(400).send({
|
|
1162
|
+
success: false,
|
|
1163
|
+
error: "Invalid request: models must be an array"
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
const registeredModels = [];
|
|
1167
|
+
const errors = [];
|
|
1168
|
+
for (const modelConfig of models) {
|
|
1169
|
+
if (!modelConfig.key || !modelConfig.model || !modelConfig.provider) {
|
|
1170
|
+
errors.push(
|
|
1171
|
+
`Model configuration is incomplete: key, model, and provider are required`
|
|
1172
|
+
);
|
|
1173
|
+
continue;
|
|
1174
|
+
}
|
|
1175
|
+
try {
|
|
1176
|
+
if (modelLatticeManager.hasLattice(modelConfig.key)) {
|
|
1177
|
+
modelLatticeManager.removeLattice(modelConfig.key);
|
|
1178
|
+
}
|
|
1179
|
+
const llmConfig = {
|
|
1180
|
+
provider: modelConfig.provider,
|
|
1181
|
+
model: modelConfig.model,
|
|
1182
|
+
streaming: modelConfig.streaming ?? false,
|
|
1183
|
+
apiKey: modelConfig.apiKey,
|
|
1184
|
+
baseURL: modelConfig.baseURL,
|
|
1185
|
+
maxTokens: modelConfig.maxTokens,
|
|
1186
|
+
temperature: modelConfig.temperature,
|
|
1187
|
+
timeout: modelConfig.timeout,
|
|
1188
|
+
maxRetries: modelConfig.maxRetries
|
|
1189
|
+
};
|
|
1190
|
+
registerModelLattice(modelConfig.key, llmConfig);
|
|
1191
|
+
registeredModels.push(modelConfig.key);
|
|
1192
|
+
} catch (error) {
|
|
1193
|
+
errors.push(
|
|
1194
|
+
`Failed to register model ${modelConfig.key}: ${error.message}`
|
|
1195
|
+
);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
if (errors.length > 0 && registeredModels.length === 0) {
|
|
1199
|
+
return reply.status(400).send({
|
|
1200
|
+
success: false,
|
|
1201
|
+
error: errors.join("; ")
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
return reply.send({
|
|
1205
|
+
success: true,
|
|
1206
|
+
message: `Successfully registered ${registeredModels.length} model(s)`,
|
|
1207
|
+
data: {
|
|
1208
|
+
registered: registeredModels,
|
|
1209
|
+
errors: errors.length > 0 ? errors : void 0
|
|
1210
|
+
}
|
|
1211
|
+
});
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
console.error("Failed to update models", {
|
|
1214
|
+
error: error.message,
|
|
1215
|
+
stack: error.stack
|
|
1216
|
+
});
|
|
1217
|
+
return reply.status(500).send({
|
|
1218
|
+
success: false,
|
|
1219
|
+
error: error.message || "Failed to update models"
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
|
|
548
1224
|
// src/schemas/index.ts
|
|
549
1225
|
var getAllMemoryItemsSchema = {
|
|
550
1226
|
description: "Get all memory items for an assistant thread",
|
|
@@ -713,6 +1389,77 @@ var triggerAgentTaskSchema = {
|
|
|
713
1389
|
}
|
|
714
1390
|
}
|
|
715
1391
|
};
|
|
1392
|
+
var updateConfigSchema = {
|
|
1393
|
+
description: "Update gateway configuration",
|
|
1394
|
+
tags: ["Configuration"],
|
|
1395
|
+
summary: "Update Configuration",
|
|
1396
|
+
body: {
|
|
1397
|
+
type: "object",
|
|
1398
|
+
properties: {
|
|
1399
|
+
config: {
|
|
1400
|
+
type: "object",
|
|
1401
|
+
description: "Configuration object to update",
|
|
1402
|
+
properties: {
|
|
1403
|
+
port: { type: "number", description: "Server port" },
|
|
1404
|
+
queueServiceType: {
|
|
1405
|
+
type: "string",
|
|
1406
|
+
enum: ["memory", "redis"],
|
|
1407
|
+
description: "Queue service type"
|
|
1408
|
+
},
|
|
1409
|
+
redisUrl: { type: "string", description: "Redis URL" },
|
|
1410
|
+
redisPassword: { type: "string", description: "Redis password" },
|
|
1411
|
+
queueName: { type: "string", description: "Queue name" }
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
},
|
|
1415
|
+
required: ["config"]
|
|
1416
|
+
},
|
|
1417
|
+
response: {
|
|
1418
|
+
200: {
|
|
1419
|
+
type: "object",
|
|
1420
|
+
properties: {
|
|
1421
|
+
success: { type: "boolean" },
|
|
1422
|
+
message: { type: "string" },
|
|
1423
|
+
data: { type: "object" }
|
|
1424
|
+
}
|
|
1425
|
+
},
|
|
1426
|
+
400: {
|
|
1427
|
+
type: "object",
|
|
1428
|
+
properties: {
|
|
1429
|
+
success: { type: "boolean" },
|
|
1430
|
+
error: { type: "string" }
|
|
1431
|
+
}
|
|
1432
|
+
},
|
|
1433
|
+
500: {
|
|
1434
|
+
type: "object",
|
|
1435
|
+
properties: {
|
|
1436
|
+
success: { type: "boolean" },
|
|
1437
|
+
error: { type: "string" }
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
};
|
|
1442
|
+
var getConfigSchema = {
|
|
1443
|
+
description: "Get current gateway configuration",
|
|
1444
|
+
tags: ["Configuration"],
|
|
1445
|
+
summary: "Get Configuration",
|
|
1446
|
+
response: {
|
|
1447
|
+
200: {
|
|
1448
|
+
type: "object",
|
|
1449
|
+
properties: {
|
|
1450
|
+
success: { type: "boolean" },
|
|
1451
|
+
data: { type: "object" }
|
|
1452
|
+
}
|
|
1453
|
+
},
|
|
1454
|
+
500: {
|
|
1455
|
+
type: "object",
|
|
1456
|
+
properties: {
|
|
1457
|
+
success: { type: "boolean" },
|
|
1458
|
+
error: { type: "string" }
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
};
|
|
716
1463
|
|
|
717
1464
|
// src/routes/index.ts
|
|
718
1465
|
var registerLatticeRoutes = (app2) => {
|
|
@@ -748,6 +1495,11 @@ var registerLatticeRoutes = (app2) => {
|
|
|
748
1495
|
{ schema: clearMemorySchema },
|
|
749
1496
|
clearMemory
|
|
750
1497
|
);
|
|
1498
|
+
app2.get("/api/assistants", getAssistantList);
|
|
1499
|
+
app2.get("/api/assistants/:id", getAssistant);
|
|
1500
|
+
app2.post("/api/assistants", createAssistant);
|
|
1501
|
+
app2.put("/api/assistants/:id", updateAssistant);
|
|
1502
|
+
app2.delete("/api/assistants/:id", deleteAssistant);
|
|
751
1503
|
app2.get(
|
|
752
1504
|
"/api/assistants/:assistantId/graph",
|
|
753
1505
|
{ schema: getAgentGraphSchema },
|
|
@@ -758,6 +1510,32 @@ var registerLatticeRoutes = (app2) => {
|
|
|
758
1510
|
{ schema: triggerAgentTaskSchema },
|
|
759
1511
|
triggerAgentTask
|
|
760
1512
|
);
|
|
1513
|
+
app2.get("/api/assistants/:assistantId/threads", getThreadList);
|
|
1514
|
+
app2.get(
|
|
1515
|
+
"/api/assistants/:assistantId/threads/:threadId",
|
|
1516
|
+
getThread
|
|
1517
|
+
);
|
|
1518
|
+
app2.post("/api/assistants/:assistantId/threads", createThread);
|
|
1519
|
+
app2.put(
|
|
1520
|
+
"/api/assistants/:assistantId/threads/:threadId",
|
|
1521
|
+
updateThread
|
|
1522
|
+
);
|
|
1523
|
+
app2.delete(
|
|
1524
|
+
"/api/assistants/:assistantId/threads/:threadId",
|
|
1525
|
+
deleteThread
|
|
1526
|
+
);
|
|
1527
|
+
app2.get(
|
|
1528
|
+
"/api/config",
|
|
1529
|
+
{ schema: getConfigSchema },
|
|
1530
|
+
getConfig
|
|
1531
|
+
);
|
|
1532
|
+
app2.put(
|
|
1533
|
+
"/api/config",
|
|
1534
|
+
{ schema: updateConfigSchema },
|
|
1535
|
+
updateConfig
|
|
1536
|
+
);
|
|
1537
|
+
app2.get("/api/models", getModels);
|
|
1538
|
+
app2.put("/api/models", updateModels);
|
|
761
1539
|
};
|
|
762
1540
|
|
|
763
1541
|
// src/logger/Logger.ts
|
|
@@ -960,54 +1738,6 @@ var configureSwagger = async (app2, customSwaggerConfig, customSwaggerUiConfig)
|
|
|
960
1738
|
await app2.register(swaggerUi, swaggerUiConfig);
|
|
961
1739
|
};
|
|
962
1740
|
|
|
963
|
-
// src/services/queue_service.ts
|
|
964
|
-
import {
|
|
965
|
-
queueLatticeManager,
|
|
966
|
-
registerQueueLattice,
|
|
967
|
-
getQueueLattice
|
|
968
|
-
} from "@axiom-lattice/core";
|
|
969
|
-
import { QueueType } from "@axiom-lattice/protocols";
|
|
970
|
-
import { RedisQueueClient } from "@axiom-lattice/queue-redis";
|
|
971
|
-
var DEFAULT_QUEUE_KEY = "default";
|
|
972
|
-
var queueServiceType = process.env.QUEUE_SERVICE_TYPE || "memory";
|
|
973
|
-
var setQueueServiceType = (type) => {
|
|
974
|
-
queueServiceType = type;
|
|
975
|
-
console.log(`Queue service type set to: ${type}`);
|
|
976
|
-
const queueName = process.env.QUEUE_NAME || "tasks";
|
|
977
|
-
const config = {
|
|
978
|
-
name: "Default Queue Service",
|
|
979
|
-
description: `Default ${type} queue service`,
|
|
980
|
-
type: type === "redis" ? QueueType.REDIS : QueueType.MEMORY,
|
|
981
|
-
queueName,
|
|
982
|
-
options: type === "redis" ? {
|
|
983
|
-
redisUrl: process.env.REDIS_URL,
|
|
984
|
-
redisPassword: process.env.REDIS_PASSWORD
|
|
985
|
-
} : void 0
|
|
986
|
-
};
|
|
987
|
-
if (queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
|
|
988
|
-
queueLatticeManager.removeLattice(DEFAULT_QUEUE_KEY);
|
|
989
|
-
}
|
|
990
|
-
let client;
|
|
991
|
-
if (type === "redis") {
|
|
992
|
-
client = new RedisQueueClient(queueName, {
|
|
993
|
-
redisUrl: process.env.REDIS_URL,
|
|
994
|
-
redisPassword: process.env.REDIS_PASSWORD
|
|
995
|
-
});
|
|
996
|
-
}
|
|
997
|
-
registerQueueLattice(DEFAULT_QUEUE_KEY, config, client);
|
|
998
|
-
};
|
|
999
|
-
var getQueueService = () => {
|
|
1000
|
-
if (!queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
|
|
1001
|
-
setQueueServiceType(queueServiceType);
|
|
1002
|
-
}
|
|
1003
|
-
return getQueueLattice(DEFAULT_QUEUE_KEY);
|
|
1004
|
-
};
|
|
1005
|
-
var popAgentTaskFromQueue = async () => {
|
|
1006
|
-
const queue = getQueueService();
|
|
1007
|
-
const result = await queue.pop();
|
|
1008
|
-
return result;
|
|
1009
|
-
};
|
|
1010
|
-
|
|
1011
1741
|
// src/services/agent_task_consumer.ts
|
|
1012
1742
|
import { eventBus, AGENT_TASK_EVENT } from "@axiom-lattice/core";
|
|
1013
1743
|
var handleAgentTask = async (taskRequest, retryCount = 0) => {
|