@axiom-lattice/gateway 2.1.12 → 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/dist/index.mjs CHANGED
@@ -927,6 +927,300 @@ async function deleteThread(request, reply) {
927
927
  };
928
928
  }
929
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
+
930
1224
  // src/schemas/index.ts
931
1225
  var getAllMemoryItemsSchema = {
932
1226
  description: "Get all memory items for an assistant thread",
@@ -1095,6 +1389,77 @@ var triggerAgentTaskSchema = {
1095
1389
  }
1096
1390
  }
1097
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
+ };
1098
1463
 
1099
1464
  // src/routes/index.ts
1100
1465
  var registerLatticeRoutes = (app2) => {
@@ -1159,6 +1524,18 @@ var registerLatticeRoutes = (app2) => {
1159
1524
  "/api/assistants/:assistantId/threads/:threadId",
1160
1525
  deleteThread
1161
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);
1162
1539
  };
1163
1540
 
1164
1541
  // src/logger/Logger.ts
@@ -1361,54 +1738,6 @@ var configureSwagger = async (app2, customSwaggerConfig, customSwaggerUiConfig)
1361
1738
  await app2.register(swaggerUi, swaggerUiConfig);
1362
1739
  };
1363
1740
 
1364
- // src/services/queue_service.ts
1365
- import {
1366
- queueLatticeManager,
1367
- registerQueueLattice,
1368
- getQueueLattice
1369
- } from "@axiom-lattice/core";
1370
- import { QueueType } from "@axiom-lattice/protocols";
1371
- import { RedisQueueClient } from "@axiom-lattice/queue-redis";
1372
- var DEFAULT_QUEUE_KEY = "default";
1373
- var queueServiceType = process.env.QUEUE_SERVICE_TYPE || "memory";
1374
- var setQueueServiceType = (type) => {
1375
- queueServiceType = type;
1376
- console.log(`Queue service type set to: ${type}`);
1377
- const queueName = process.env.QUEUE_NAME || "tasks";
1378
- const config = {
1379
- name: "Default Queue Service",
1380
- description: `Default ${type} queue service`,
1381
- type: type === "redis" ? QueueType.REDIS : QueueType.MEMORY,
1382
- queueName,
1383
- options: type === "redis" ? {
1384
- redisUrl: process.env.REDIS_URL,
1385
- redisPassword: process.env.REDIS_PASSWORD
1386
- } : void 0
1387
- };
1388
- if (queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
1389
- queueLatticeManager.removeLattice(DEFAULT_QUEUE_KEY);
1390
- }
1391
- let client;
1392
- if (type === "redis") {
1393
- client = new RedisQueueClient(queueName, {
1394
- redisUrl: process.env.REDIS_URL,
1395
- redisPassword: process.env.REDIS_PASSWORD
1396
- });
1397
- }
1398
- registerQueueLattice(DEFAULT_QUEUE_KEY, config, client);
1399
- };
1400
- var getQueueService = () => {
1401
- if (!queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
1402
- setQueueServiceType(queueServiceType);
1403
- }
1404
- return getQueueLattice(DEFAULT_QUEUE_KEY);
1405
- };
1406
- var popAgentTaskFromQueue = async () => {
1407
- const queue = getQueueService();
1408
- const result = await queue.pop();
1409
- return result;
1410
- };
1411
-
1412
1741
  // src/services/agent_task_consumer.ts
1413
1742
  import { eventBus, AGENT_TASK_EVENT } from "@axiom-lattice/core";
1414
1743
  var handleAgentTask = async (taskRequest, retryCount = 0) => {