@axiom-lattice/gateway 2.1.18 → 2.1.20

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.js CHANGED
@@ -62,13 +62,15 @@ async function agent_invoke({
62
62
  command,
63
63
  run_id
64
64
  }) {
65
- const runnable_agent = (0, import_core.getAgentClient)(assistant_id);
65
+ const agentLattice = (0, import_core.getAgentLattice)(assistant_id);
66
+ const runnable_agent = agentLattice?.client;
66
67
  const { message, ...rest } = input;
67
68
  const humanMessage = new import_messages.HumanMessage(message || "");
68
69
  const messages = [humanMessage];
69
70
  if (!runnable_agent) {
70
71
  throw new Error(`Agent ${assistant_id} not found`);
71
72
  }
73
+ const runConfig = agentLattice?.config?.runConfig || {};
72
74
  const result = await runnable_agent.invoke(
73
75
  command ? new import_langgraph.Command(command) : { ...rest, messages, "x-tenant-id": tenant_id },
74
76
  {
@@ -77,7 +79,9 @@ async function agent_invoke({
77
79
  run_id: run_id || (0, import_uuid.v4)(),
78
80
  "x-tenant-id": tenant_id,
79
81
  "x-request-id": run_id,
80
- "x-thread-id": thread_id
82
+ "x-thread-id": thread_id,
83
+ runConfig
84
+ // Inject runConfig for tools to access
81
85
  },
82
86
  recursionLimit: 200
83
87
  }
@@ -100,6 +104,7 @@ async function agent_stream({
100
104
  run_id
101
105
  }) {
102
106
  const runnable_agent = (0, import_core.getAgentClient)(assistant_id);
107
+ const agentLattice = (0, import_core.getAgentLattice)(assistant_id);
103
108
  const { message, ...rest } = input;
104
109
  let messages = [];
105
110
  if (!command) {
@@ -107,6 +112,7 @@ async function agent_stream({
107
112
  messages = [humanMessage];
108
113
  }
109
114
  const chunkBuffer = getOrCreateChunkBuffer();
115
+ const runConfig = agentLattice?.config?.runConfig || {};
110
116
  try {
111
117
  if (!runnable_agent) {
112
118
  throw new Error(`Agent ${assistant_id} not found`);
@@ -123,7 +129,9 @@ async function agent_stream({
123
129
  run_id: run_id || (0, import_uuid.v4)(),
124
130
  "x-tenant-id": tenant_id,
125
131
  "x-request-id": run_id,
126
- "x-thread-id": thread_id
132
+ "x-thread-id": thread_id,
133
+ runConfig
134
+ // Inject runConfig for tools to access
127
135
  },
128
136
  streamMode: ["updates", "messages"],
129
137
  subgraphs: false,
@@ -823,6 +831,201 @@ async function deleteThread(request, reply) {
823
831
  };
824
832
  }
825
833
 
834
+ // src/controllers/schedules.ts
835
+ var import_core6 = require("@axiom-lattice/core");
836
+ function getScheduleLattice() {
837
+ const keys = import_core6.scheduleLatticeManager.getLatticeKeys();
838
+ if (keys.length === 0) {
839
+ return null;
840
+ }
841
+ if (import_core6.scheduleLatticeManager.hasLattice("default")) {
842
+ return import_core6.scheduleLatticeManager.getScheduleLattice("default");
843
+ }
844
+ return import_core6.scheduleLatticeManager.getScheduleLattice(keys[0]);
845
+ }
846
+ async function getThreadSchedules(request, reply) {
847
+ const { assistantId, threadId } = request.params;
848
+ const { status, limit, offset } = request.query;
849
+ try {
850
+ const scheduleLattice = getScheduleLattice();
851
+ if (!scheduleLattice) {
852
+ return {
853
+ success: true,
854
+ message: "No schedule lattice configured",
855
+ data: {
856
+ records: [],
857
+ total: 0
858
+ }
859
+ };
860
+ }
861
+ const storage = scheduleLattice.client.getStorage();
862
+ if (!storage) {
863
+ return {
864
+ success: true,
865
+ message: "No schedule storage configured",
866
+ data: {
867
+ records: [],
868
+ total: 0
869
+ }
870
+ };
871
+ }
872
+ const filters = {
873
+ threadId,
874
+ assistantId
875
+ };
876
+ if (status) {
877
+ filters.status = status;
878
+ }
879
+ if (limit) {
880
+ filters.limit = parseInt(limit, 10);
881
+ }
882
+ if (offset) {
883
+ filters.offset = parseInt(offset, 10);
884
+ }
885
+ const tasks = await storage.getAllTasks(filters);
886
+ const total = await storage.countTasks({
887
+ threadId,
888
+ assistantId,
889
+ status
890
+ });
891
+ return {
892
+ success: true,
893
+ message: "Successfully retrieved scheduled tasks",
894
+ data: {
895
+ records: tasks,
896
+ total
897
+ }
898
+ };
899
+ } catch (error) {
900
+ request.log.error(error, "Failed to get thread schedules");
901
+ return reply.status(500).send({
902
+ success: false,
903
+ message: "Failed to retrieve scheduled tasks",
904
+ data: {
905
+ records: [],
906
+ total: 0
907
+ }
908
+ });
909
+ }
910
+ }
911
+ async function getScheduledTask(request, reply) {
912
+ const { taskId } = request.params;
913
+ try {
914
+ const scheduleLattice = getScheduleLattice();
915
+ if (!scheduleLattice) {
916
+ return reply.status(404).send({
917
+ success: false,
918
+ message: "No schedule lattice configured"
919
+ });
920
+ }
921
+ const task = await scheduleLattice.client.getTask(taskId);
922
+ if (!task) {
923
+ return reply.status(404).send({
924
+ success: false,
925
+ message: "Scheduled task not found"
926
+ });
927
+ }
928
+ return {
929
+ success: true,
930
+ message: "Successfully retrieved scheduled task",
931
+ data: task
932
+ };
933
+ } catch (error) {
934
+ request.log.error(error, "Failed to get scheduled task");
935
+ return reply.status(500).send({
936
+ success: false,
937
+ message: "Failed to retrieve scheduled task"
938
+ });
939
+ }
940
+ }
941
+ async function cancelScheduledTask(request, reply) {
942
+ const { taskId } = request.params;
943
+ try {
944
+ const scheduleLattice = getScheduleLattice();
945
+ if (!scheduleLattice) {
946
+ return reply.status(404).send({
947
+ success: false,
948
+ message: "No schedule lattice configured"
949
+ });
950
+ }
951
+ const result = await scheduleLattice.client.cancel(taskId);
952
+ if (!result) {
953
+ return reply.status(404).send({
954
+ success: false,
955
+ message: "Scheduled task not found or already cancelled"
956
+ });
957
+ }
958
+ return {
959
+ success: true,
960
+ message: "Successfully cancelled scheduled task"
961
+ };
962
+ } catch (error) {
963
+ request.log.error(error, "Failed to cancel scheduled task");
964
+ return reply.status(500).send({
965
+ success: false,
966
+ message: "Failed to cancel scheduled task"
967
+ });
968
+ }
969
+ }
970
+ async function pauseScheduledTask(request, reply) {
971
+ const { taskId } = request.params;
972
+ try {
973
+ const scheduleLattice = getScheduleLattice();
974
+ if (!scheduleLattice) {
975
+ return reply.status(404).send({
976
+ success: false,
977
+ message: "No schedule lattice configured"
978
+ });
979
+ }
980
+ const result = await scheduleLattice.client.pause(taskId);
981
+ if (!result) {
982
+ return reply.status(404).send({
983
+ success: false,
984
+ message: "Scheduled task not found or cannot be paused"
985
+ });
986
+ }
987
+ return {
988
+ success: true,
989
+ message: "Successfully paused scheduled task"
990
+ };
991
+ } catch (error) {
992
+ request.log.error(error, "Failed to pause scheduled task");
993
+ return reply.status(500).send({
994
+ success: false,
995
+ message: "Failed to pause scheduled task"
996
+ });
997
+ }
998
+ }
999
+ async function resumeScheduledTask(request, reply) {
1000
+ const { taskId } = request.params;
1001
+ try {
1002
+ const scheduleLattice = getScheduleLattice();
1003
+ if (!scheduleLattice) {
1004
+ return reply.status(404).send({
1005
+ success: false,
1006
+ message: "No schedule lattice configured"
1007
+ });
1008
+ }
1009
+ const result = await scheduleLattice.client.resume(taskId);
1010
+ if (!result) {
1011
+ return reply.status(404).send({
1012
+ success: false,
1013
+ message: "Scheduled task not found or cannot be resumed"
1014
+ });
1015
+ }
1016
+ return {
1017
+ success: true,
1018
+ message: "Successfully resumed scheduled task"
1019
+ };
1020
+ } catch (error) {
1021
+ request.log.error(error, "Failed to resume scheduled task");
1022
+ return reply.status(500).send({
1023
+ success: false,
1024
+ message: "Failed to resume scheduled task"
1025
+ });
1026
+ }
1027
+ }
1028
+
826
1029
  // src/config.ts
827
1030
  var ConfigService = class {
828
1031
  constructor() {
@@ -896,7 +1099,7 @@ var ConfigService = class {
896
1099
  var configService = new ConfigService();
897
1100
 
898
1101
  // src/services/queue_service.ts
899
- var import_core6 = require("@axiom-lattice/core");
1102
+ var import_core7 = require("@axiom-lattice/core");
900
1103
  var import_protocols = require("@axiom-lattice/protocols");
901
1104
  var import_queue_redis = require("@axiom-lattice/queue-redis");
902
1105
  var DEFAULT_QUEUE_KEY = "default";
@@ -915,8 +1118,8 @@ var setQueueServiceType = (type) => {
915
1118
  redisPassword: process.env.REDIS_PASSWORD
916
1119
  } : void 0
917
1120
  };
918
- if (import_core6.queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
919
- import_core6.queueLatticeManager.removeLattice(DEFAULT_QUEUE_KEY);
1121
+ if (import_core7.queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
1122
+ import_core7.queueLatticeManager.removeLattice(DEFAULT_QUEUE_KEY);
920
1123
  }
921
1124
  let client;
922
1125
  if (type === "redis") {
@@ -925,13 +1128,13 @@ var setQueueServiceType = (type) => {
925
1128
  redisPassword: process.env.REDIS_PASSWORD
926
1129
  });
927
1130
  }
928
- (0, import_core6.registerQueueLattice)(DEFAULT_QUEUE_KEY, config, client);
1131
+ (0, import_core7.registerQueueLattice)(DEFAULT_QUEUE_KEY, config, client);
929
1132
  };
930
1133
  var getQueueService = () => {
931
- if (!import_core6.queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
1134
+ if (!import_core7.queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
932
1135
  setQueueServiceType(queueServiceType);
933
1136
  }
934
- return (0, import_core6.getQueueLattice)(DEFAULT_QUEUE_KEY);
1137
+ return (0, import_core7.getQueueLattice)(DEFAULT_QUEUE_KEY);
935
1138
  };
936
1139
  var popAgentTaskFromQueue = async () => {
937
1140
  const queue = getQueueService();
@@ -1012,10 +1215,10 @@ async function getConfig(request, reply) {
1012
1215
  }
1013
1216
 
1014
1217
  // src/controllers/models.ts
1015
- var import_core7 = require("@axiom-lattice/core");
1218
+ var import_core8 = require("@axiom-lattice/core");
1016
1219
  async function getModels(request, reply) {
1017
1220
  try {
1018
- const allLattices = import_core7.modelLatticeManager.getAllLattices();
1221
+ const allLattices = import_core8.modelLatticeManager.getAllLattices();
1019
1222
  const models = allLattices.map((lattice) => {
1020
1223
  const config = lattice.client.config || {};
1021
1224
  return {
@@ -1065,8 +1268,8 @@ async function updateModels(request, reply) {
1065
1268
  continue;
1066
1269
  }
1067
1270
  try {
1068
- if (import_core7.modelLatticeManager.hasLattice(modelConfig.key)) {
1069
- import_core7.modelLatticeManager.removeLattice(modelConfig.key);
1271
+ if (import_core8.modelLatticeManager.hasLattice(modelConfig.key)) {
1272
+ import_core8.modelLatticeManager.removeLattice(modelConfig.key);
1070
1273
  }
1071
1274
  const llmConfig = {
1072
1275
  provider: modelConfig.provider,
@@ -1079,7 +1282,7 @@ async function updateModels(request, reply) {
1079
1282
  timeout: modelConfig.timeout,
1080
1283
  maxRetries: modelConfig.maxRetries
1081
1284
  };
1082
- (0, import_core7.registerModelLattice)(modelConfig.key, llmConfig);
1285
+ (0, import_core8.registerModelLattice)(modelConfig.key, llmConfig);
1083
1286
  registeredModels.push(modelConfig.key);
1084
1287
  } catch (error) {
1085
1288
  errors.push(
@@ -1487,144 +1690,14 @@ var registerLatticeRoutes = (app2) => {
1487
1690
  { schema: getHealthSchema },
1488
1691
  getHealth
1489
1692
  );
1490
- };
1491
-
1492
- // src/logger/Logger.ts
1493
- var import_pino = __toESM(require("pino"));
1494
- var import_pino_pretty = require("pino-pretty");
1495
- var import_pino_roll = require("pino-roll");
1496
- var PinoLoggerFactory = class _PinoLoggerFactory {
1497
- constructor() {
1498
- const isProd = process.env.NODE_ENV === "production";
1499
- const loggerConfig = {
1500
- // 自定义时间戳格式
1501
- timestamp: () => `,"@timestamp":"${(/* @__PURE__ */ new Date()).toISOString()}"`,
1502
- // 关闭默认的时间戳键
1503
- base: {
1504
- "@version": "1",
1505
- app_name: "lattice",
1506
- service_name: "lattice/graph-server",
1507
- thread_name: "main",
1508
- logger_name: "lattice-graph-logger"
1509
- },
1510
- formatters: {
1511
- level: (label, number) => {
1512
- return {
1513
- level: label.toUpperCase(),
1514
- level_value: number * 1e3
1515
- };
1516
- }
1517
- }
1518
- };
1519
- if (isProd) {
1520
- try {
1521
- this.pinoLogger = (0, import_pino.default)(
1522
- loggerConfig,
1523
- import_pino.default.transport({
1524
- target: "pino-roll",
1525
- options: {
1526
- file: "./logs/fin_ai_graph_server",
1527
- frequency: "daily",
1528
- mkdir: true
1529
- }
1530
- })
1531
- );
1532
- } catch (error) {
1533
- console.error(
1534
- "\u65E0\u6CD5\u521D\u59CB\u5316 pino-roll \u65E5\u5FD7\u8BB0\u5F55\u5668\uFF0C\u56DE\u9000\u5230\u63A7\u5236\u53F0\u65E5\u5FD7",
1535
- error
1536
- );
1537
- this.pinoLogger = (0, import_pino.default)({
1538
- ...loggerConfig,
1539
- transport: {
1540
- target: "pino-pretty",
1541
- options: {
1542
- colorize: true
1543
- }
1544
- }
1545
- });
1546
- }
1547
- } else {
1548
- this.pinoLogger = (0, import_pino.default)({
1549
- ...loggerConfig,
1550
- transport: {
1551
- target: "pino-pretty",
1552
- options: {
1553
- colorize: true
1554
- }
1555
- }
1556
- });
1557
- }
1558
- }
1559
- static getInstance() {
1560
- if (!_PinoLoggerFactory.instance) {
1561
- _PinoLoggerFactory.instance = new _PinoLoggerFactory();
1562
- }
1563
- return _PinoLoggerFactory.instance;
1564
- }
1565
- getPinoLogger() {
1566
- return this.pinoLogger;
1567
- }
1568
- };
1569
- var Logger = class _Logger {
1570
- constructor(options) {
1571
- this.context = options?.context || {};
1572
- this.name = options?.name || "lattice-graph-logger";
1573
- this.serviceName = options?.serviceName || "lattice/graph-server";
1574
- }
1575
- /**
1576
- * 获取合并了上下文的日志对象
1577
- * @param additionalContext 额外的上下文数据
1578
- * @returns 带有上下文的pino日志对象
1579
- */
1580
- getContextualLogger(additionalContext) {
1581
- const pinoLogger = PinoLoggerFactory.getInstance().getPinoLogger();
1582
- const contextObj = {
1583
- "x-user-id": this.context["x-user-id"] || "",
1584
- "x-tenant-id": this.context["x-tenant-id"] || "",
1585
- "x-request-id": this.context["x-request-id"] || "",
1586
- "x-task-id": this.context["x-task-id"] || "",
1587
- "x-thread-id": this.context["x-thread-id"] || "",
1588
- service_name: this.serviceName,
1589
- logger_name: this.name,
1590
- ...additionalContext
1591
- };
1592
- return pinoLogger.child(contextObj);
1593
- }
1594
- info(msg, obj) {
1595
- this.getContextualLogger(obj).info(msg);
1596
- }
1597
- error(msg, obj) {
1598
- this.getContextualLogger(obj).error(msg);
1599
- }
1600
- warn(msg, obj) {
1601
- this.getContextualLogger(obj).warn(msg);
1602
- }
1603
- debug(msg, obj) {
1604
- this.getContextualLogger(obj).debug(msg);
1605
- }
1606
- /**
1607
- * 更新Logger实例的上下文
1608
- */
1609
- updateContext(context) {
1610
- this.context = {
1611
- ...this.context,
1612
- ...context
1613
- };
1614
- }
1615
- /**
1616
- * 创建一个新的Logger实例,继承当前Logger的上下文
1617
- */
1618
- child(options) {
1619
- return new _Logger({
1620
- name: options.name || this.name,
1621
- serviceName: options.serviceName || this.serviceName,
1622
- context: {
1623
- ...this.context,
1624
- ...options.context
1625
- }
1626
- });
1627
- }
1693
+ app2.get(
1694
+ "/api/assistants/:assistantId/threads/:threadId/schedules",
1695
+ getThreadSchedules
1696
+ );
1697
+ app2.get("/api/schedules/:taskId", getScheduledTask);
1698
+ app2.post("/api/schedules/:taskId/cancel", cancelScheduledTask);
1699
+ app2.post("/api/schedules/:taskId/pause", pauseScheduledTask);
1700
+ app2.post("/api/schedules/:taskId/resume", resumeScheduledTask);
1628
1701
  };
1629
1702
 
1630
1703
  // src/swagger.ts
@@ -1690,7 +1763,7 @@ var configureSwagger = async (app2, customSwaggerConfig, customSwaggerUiConfig)
1690
1763
  };
1691
1764
 
1692
1765
  // src/services/agent_task_consumer.ts
1693
- var import_core8 = require("@axiom-lattice/core");
1766
+ var import_core9 = require("@axiom-lattice/core");
1694
1767
  var handleAgentTask = async (taskRequest, retryCount = 0) => {
1695
1768
  const {
1696
1769
  assistant_id,
@@ -1754,7 +1827,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
1754
1827
  }
1755
1828
  if (callback_event) {
1756
1829
  const state = await agent_state({ assistant_id, thread_id });
1757
- import_core8.eventBus.publish(callback_event, {
1830
+ import_core9.eventBus.publish(callback_event, {
1758
1831
  success: true,
1759
1832
  state,
1760
1833
  config: { assistant_id, thread_id, tenant_id }
@@ -1768,7 +1841,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
1768
1841
  await response.text();
1769
1842
  if (callback_event) {
1770
1843
  const state = await agent_state({ assistant_id, thread_id });
1771
- import_core8.eventBus.publish(callback_event, {
1844
+ import_core9.eventBus.publish(callback_event, {
1772
1845
  success: true,
1773
1846
  state,
1774
1847
  config: { assistant_id, thread_id, tenant_id }
@@ -1795,7 +1868,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
1795
1868
  return handleAgentTask(taskRequest, nextRetryCount);
1796
1869
  }
1797
1870
  if (callback_event) {
1798
- import_core8.eventBus.publish(callback_event, {
1871
+ import_core9.eventBus.publish(callback_event, {
1799
1872
  success: false,
1800
1873
  error: error instanceof Error ? error.message : String(error),
1801
1874
  config: { assistant_id, thread_id, tenant_id }
@@ -1833,7 +1906,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
1833
1906
  * 初始化事件监听和队列轮询
1834
1907
  */
1835
1908
  initialize() {
1836
- import_core8.eventBus.subscribe(import_core8.AGENT_TASK_EVENT, this.trigger_agent_task.bind(this));
1909
+ import_core9.eventBus.subscribe(import_core9.AGENT_TASK_EVENT, this.trigger_agent_task.bind(this));
1837
1910
  this.startPollingQueue();
1838
1911
  console.log("Agent\u4EFB\u52A1\u6D88\u8D39\u8005\u5DF2\u542F\u52A8\u5E76\u76D1\u542C\u4EFB\u52A1\u4E8B\u4EF6\u548C\u961F\u5217");
1839
1912
  }
@@ -1952,7 +2025,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
1952
2025
  handleAgentTask(taskRequest).catch((error) => {
1953
2026
  console.error("\u5904\u7406Agent\u4EFB\u52A1\u65F6\u53D1\u751F\u672A\u6355\u83B7\u7684\u9519\u8BEF:", error);
1954
2027
  if (taskRequest.callback_event) {
1955
- import_core8.eventBus.publish(taskRequest.callback_event, {
2028
+ import_core9.eventBus.publish(taskRequest.callback_event, {
1956
2029
  success: false,
1957
2030
  error: error instanceof Error ? error.message : String(error),
1958
2031
  config: {
@@ -1972,13 +2045,27 @@ _AgentTaskConsumer.agent_run_endpoint = "http://localhost:4001/api/runs";
1972
2045
  var AgentTaskConsumer = _AgentTaskConsumer;
1973
2046
 
1974
2047
  // src/index.ts
2048
+ var import_core10 = require("@axiom-lattice/core");
2049
+ var import_protocols2 = require("@axiom-lattice/protocols");
1975
2050
  process.on("unhandledRejection", (reason, promise) => {
1976
2051
  console.error("\u672A\u5904\u7406\u7684Promise\u62D2\u7EDD:", reason);
1977
2052
  });
1978
- var logger = new Logger({
1979
- serviceName: "lattice-gateway",
1980
- name: "fastify-server"
1981
- });
2053
+ var DEFAULT_LOGGER_CONFIG = {
2054
+ name: "default",
2055
+ description: "Default logger for lattice-gateway service",
2056
+ type: import_protocols2.LoggerType.PINO,
2057
+ serviceName: "lattice/gateway",
2058
+ loggerName: "lattice/gateway"
2059
+ };
2060
+ var loggerLattice = initializeLogger(DEFAULT_LOGGER_CONFIG);
2061
+ var logger = loggerLattice.client;
2062
+ function initializeLogger(config) {
2063
+ if (import_core10.loggerLatticeManager.hasLattice("default")) {
2064
+ import_core10.loggerLatticeManager.removeLattice("default");
2065
+ }
2066
+ (0, import_core10.registerLoggerLattice)("default", config);
2067
+ return (0, import_core10.getLoggerLattice)("default");
2068
+ }
1982
2069
  var app = (0, import_fastify.default)({
1983
2070
  logger: false,
1984
2071
  // 禁用内置日志记录器
@@ -1986,17 +2073,33 @@ var app = (0, import_fastify.default)({
1986
2073
  // Default 50MB, configurable via BODY_LIMIT env var
1987
2074
  });
1988
2075
  app.addHook("onRequest", (request, reply, done) => {
2076
+ const getHeaderValue = (header) => {
2077
+ if (Array.isArray(header)) {
2078
+ return header[0];
2079
+ }
2080
+ return header;
2081
+ };
1989
2082
  const context = {
1990
- "x-tenant-id": request.headers["x-tenant-id"],
1991
- "x-request-id": request.headers["x-request-id"]
2083
+ "x-tenant-id": getHeaderValue(request.headers["x-tenant-id"]),
2084
+ "x-request-id": getHeaderValue(request.headers["x-request-id"])
1992
2085
  };
2086
+ if (loggerLattice.updateContext) {
2087
+ loggerLattice.updateContext(context);
2088
+ }
1993
2089
  done();
1994
2090
  });
1995
2091
  app.addHook("onResponse", (request, reply, done) => {
2092
+ const getHeaderValue = (header) => {
2093
+ if (Array.isArray(header)) {
2094
+ return header[0];
2095
+ }
2096
+ return header;
2097
+ };
1996
2098
  const context = {
1997
- "x-tenant-id": request.headers["x-tenant-id"],
1998
- "x-request-id": request.headers["x-request-id"]
2099
+ "x-tenant-id": getHeaderValue(request.headers["x-tenant-id"]),
2100
+ "x-request-id": getHeaderValue(request.headers["x-request-id"])
1999
2101
  };
2102
+ loggerLattice.info(`${request.method} ${request.url} - ${reply.statusCode}`);
2000
2103
  done();
2001
2104
  });
2002
2105
  app.register(import_cors.default, {
@@ -2014,9 +2117,15 @@ app.register(import_cors.default, {
2014
2117
  });
2015
2118
  app.register(import_sensible.default);
2016
2119
  app.setErrorHandler((error, request, reply) => {
2120
+ const getHeaderValue = (header) => {
2121
+ if (Array.isArray(header)) {
2122
+ return header[0];
2123
+ }
2124
+ return header;
2125
+ };
2017
2126
  const context = {
2018
- "x-tenant-id": request.headers["x-tenant-id"],
2019
- "x-request-id": request.headers["x-request-id"]
2127
+ "x-tenant-id": getHeaderValue(request.headers["x-tenant-id"]),
2128
+ "x-request-id": getHeaderValue(request.headers["x-request-id"])
2020
2129
  };
2021
2130
  logger.error(
2022
2131
  `\u8BF7\u6C42\u9519\u8BEF: ${request.method} ${request.url} error:${error.message}`,
@@ -2032,9 +2141,19 @@ app.setErrorHandler((error, request, reply) => {
2032
2141
  error: error.message || "\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF"
2033
2142
  });
2034
2143
  });
2035
- app.decorate("logger", logger);
2036
2144
  var start = async (config) => {
2037
2145
  try {
2146
+ if (config?.loggerConfig) {
2147
+ const loggerConfig = {
2148
+ ...DEFAULT_LOGGER_CONFIG,
2149
+ ...config.loggerConfig,
2150
+ // Merge file config if provided
2151
+ file: config.loggerConfig.file || DEFAULT_LOGGER_CONFIG.file
2152
+ };
2153
+ loggerLattice = initializeLogger(loggerConfig);
2154
+ logger = loggerLattice.client;
2155
+ }
2156
+ app.decorate("loggerLattice", loggerLattice);
2038
2157
  const target_port = config?.port || Number(process.env.PORT) || 4001;
2039
2158
  await app.listen({ port: target_port, host: "0.0.0.0" });
2040
2159
  logger.info(`Lattice Gateway is running on port: ${target_port}`);