@axiom-lattice/gateway 2.1.74 → 2.1.76
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 +14 -12
- package/CHANGELOG.md +21 -0
- package/dist/index.d.mts +38 -2
- package/dist/index.d.ts +38 -2
- package/dist/index.js +741 -401
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +689 -390
- package/dist/index.mjs.map +1 -1
- package/dist/sender-PX32VSHB.mjs +32 -0
- package/dist/sender-PX32VSHB.mjs.map +1 -0
- package/package.json +7 -6
- package/src/bindings/index.ts +14 -0
- package/src/channels/__tests__/routes.test.ts +23 -44
- package/src/channels/lark/LarkChannelAdapter.ts +75 -0
- package/src/channels/lark/__tests__/controller.test.ts +62 -196
- package/src/channels/lark/controller.ts +25 -167
- package/src/channels/lark/routes.ts +12 -111
- package/src/channels/registry.ts +20 -0
- package/src/channels/routes.ts +7 -4
- package/src/controllers/channel-bindings.ts +135 -0
- package/src/controllers/channel-installations.ts +6 -3
- package/src/index.ts +38 -2
- package/src/router/MessageContext.ts +14 -0
- package/src/router/MessageRouter.ts +201 -0
- package/src/router/middlewares/auditLogger.ts +34 -0
- package/src/router/middlewares/deduplication.ts +26 -0
- package/src/router/middlewares/index.ts +3 -0
- package/src/router/middlewares/rateLimit.ts +39 -0
- package/src/routes/channel-bindings.ts +11 -0
- package/src/routes/index.ts +50 -2
package/dist/index.js
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,6 +30,44 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
33
|
+
// src/channels/lark/sender.ts
|
|
34
|
+
var sender_exports = {};
|
|
35
|
+
__export(sender_exports, {
|
|
36
|
+
createLarkSender: () => createLarkSender
|
|
37
|
+
});
|
|
38
|
+
async function createLarkSender(config, client) {
|
|
39
|
+
const resolved = client ?? await createDefaultLarkClient(config);
|
|
40
|
+
return {
|
|
41
|
+
async sendTextReply(input) {
|
|
42
|
+
const response = await resolved.im.v1.message.create({
|
|
43
|
+
params: {
|
|
44
|
+
receive_id_type: "chat_id"
|
|
45
|
+
},
|
|
46
|
+
data: {
|
|
47
|
+
receive_id: input.chatId,
|
|
48
|
+
msg_type: "text",
|
|
49
|
+
content: JSON.stringify({ text: input.text })
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (response.code && response.code !== 0) {
|
|
53
|
+
throw new Error("Failed to send Lark reply");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
async function createDefaultLarkClient(config) {
|
|
59
|
+
const Lark = await import("@larksuiteoapi/node-sdk");
|
|
60
|
+
return new Lark.Client({
|
|
61
|
+
appId: config.appId,
|
|
62
|
+
appSecret: config.appSecret
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
var init_sender = __esm({
|
|
66
|
+
"src/channels/lark/sender.ts"() {
|
|
67
|
+
"use strict";
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
30
71
|
// src/index.ts
|
|
31
72
|
var index_exports = {};
|
|
32
73
|
__export(index_exports, {
|
|
@@ -5714,9 +5755,8 @@ function registerAuthRoutes(app2, config) {
|
|
|
5714
5755
|
);
|
|
5715
5756
|
}
|
|
5716
5757
|
|
|
5717
|
-
// src/channels/lark/
|
|
5718
|
-
var
|
|
5719
|
-
var import_pg_stores = require("@axiom-lattice/pg-stores");
|
|
5758
|
+
// src/channels/lark/LarkChannelAdapter.ts
|
|
5759
|
+
var import_zod = require("zod");
|
|
5720
5760
|
|
|
5721
5761
|
// src/channels/lark/parser.ts
|
|
5722
5762
|
function parseLarkMessageEvent(payload) {
|
|
@@ -5756,279 +5796,62 @@ function normalizeChatType(chatType) {
|
|
|
5756
5796
|
return chatType === "p2p" ? "direct" : "group";
|
|
5757
5797
|
}
|
|
5758
5798
|
|
|
5759
|
-
// src/channels/lark/
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
return;
|
|
5766
|
-
}
|
|
5767
|
-
const config = await dependencies.getInstallationConfig(installationId);
|
|
5768
|
-
if (!config) {
|
|
5769
|
-
reply.status(404).send({ success: false, message: "Lark installation not found" });
|
|
5770
|
-
return;
|
|
5771
|
-
}
|
|
5772
|
-
const body = dependencies.parseRequestBody(
|
|
5773
|
-
request.body,
|
|
5774
|
-
config.encryptKey
|
|
5775
|
-
);
|
|
5776
|
-
if (!dependencies.verifyParsedBody(body, config)) {
|
|
5777
|
-
reply.status(401).send({ success: false, message: "Invalid Lark request" });
|
|
5778
|
-
return;
|
|
5779
|
-
}
|
|
5780
|
-
if (body.type === "url_verification" && body.challenge) {
|
|
5781
|
-
reply.status(200).send({ challenge: body.challenge });
|
|
5782
|
-
return;
|
|
5783
|
-
}
|
|
5784
|
-
const parsed = dependencies.parseEvent(request.body);
|
|
5785
|
-
if (!parsed) {
|
|
5786
|
-
reply.status(200).send({ success: true, ignored: true });
|
|
5787
|
-
return;
|
|
5788
|
-
}
|
|
5789
|
-
const receipt = await dependencies.claimInboundReceipt({
|
|
5790
|
-
channel: "lark",
|
|
5791
|
-
channelAppId: config.appId,
|
|
5792
|
-
externalMessageId: parsed.messageId,
|
|
5793
|
-
tenantId: config.tenantId
|
|
5794
|
-
});
|
|
5795
|
-
if (!receipt.accepted) {
|
|
5796
|
-
reply.status(200).send(
|
|
5797
|
-
receipt.status === "processing" ? { success: true, processing: true } : { success: true, duplicate: true }
|
|
5798
|
-
);
|
|
5799
|
-
return;
|
|
5800
|
-
}
|
|
5801
|
-
try {
|
|
5802
|
-
const { threadId } = await dependencies.resolveThread({
|
|
5803
|
-
channel: "lark",
|
|
5804
|
-
channelAppId: config.appId,
|
|
5805
|
-
tenantId: config.tenantId,
|
|
5806
|
-
assistantId: config.assistantId,
|
|
5807
|
-
mappingMode: config.mappingMode,
|
|
5808
|
-
openId: parsed.openId,
|
|
5809
|
-
chatId: parsed.chatId,
|
|
5810
|
-
chatType: parsed.chatType,
|
|
5811
|
-
messageId: parsed.messageId,
|
|
5812
|
-
workspaceId: config.workspaceId,
|
|
5813
|
-
projectId: config.projectId
|
|
5814
|
-
});
|
|
5815
|
-
const text = await dependencies.runAgentAndCollectText({
|
|
5816
|
-
tenantId: config.tenantId,
|
|
5817
|
-
assistantId: config.assistantId,
|
|
5818
|
-
threadId,
|
|
5819
|
-
text: parsed.text,
|
|
5820
|
-
workspaceId: config.workspaceId,
|
|
5821
|
-
projectId: config.projectId
|
|
5822
|
-
});
|
|
5823
|
-
await dependencies.sendTextReply({
|
|
5824
|
-
chatId: parsed.chatId,
|
|
5825
|
-
text,
|
|
5826
|
-
config
|
|
5827
|
-
});
|
|
5828
|
-
await dependencies.markInboundReceiptCompleted({
|
|
5829
|
-
channel: "lark",
|
|
5830
|
-
channelAppId: config.appId,
|
|
5831
|
-
externalMessageId: parsed.messageId,
|
|
5832
|
-
tenantId: config.tenantId,
|
|
5833
|
-
threadId
|
|
5834
|
-
});
|
|
5835
|
-
reply.status(200).send({ success: true, threadId });
|
|
5836
|
-
} catch (error) {
|
|
5837
|
-
await dependencies.markInboundReceiptFailed({
|
|
5838
|
-
channel: "lark",
|
|
5839
|
-
channelAppId: config.appId,
|
|
5840
|
-
externalMessageId: parsed.messageId,
|
|
5841
|
-
tenantId: config.tenantId
|
|
5842
|
-
});
|
|
5843
|
-
throw error;
|
|
5844
|
-
}
|
|
5845
|
-
};
|
|
5846
|
-
}
|
|
5847
|
-
var handleLarkEvent = createLarkEventHandler({
|
|
5848
|
-
getInstallationConfig: async () => null,
|
|
5849
|
-
parseRequestBody: (body) => body || {},
|
|
5850
|
-
verifyParsedBody: () => true,
|
|
5851
|
-
parseEvent: parseLarkMessageEvent,
|
|
5852
|
-
claimInboundReceipt: async () => ({ accepted: true, status: "processing" }),
|
|
5853
|
-
markInboundReceiptCompleted: async () => void 0,
|
|
5854
|
-
markInboundReceiptFailed: async () => void 0,
|
|
5855
|
-
resolveThread: async () => ({ threadId: "" }),
|
|
5856
|
-
runAgentAndCollectText: async () => "",
|
|
5857
|
-
sendTextReply: async () => void 0
|
|
5799
|
+
// src/channels/lark/LarkChannelAdapter.ts
|
|
5800
|
+
var larkConfigSchema = import_zod.z.object({
|
|
5801
|
+
appId: import_zod.z.string(),
|
|
5802
|
+
appSecret: import_zod.z.string(),
|
|
5803
|
+
verificationToken: import_zod.z.string().optional(),
|
|
5804
|
+
encryptKey: import_zod.z.string().optional()
|
|
5858
5805
|
});
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
function isLarkIngressEnabled(config) {
|
|
5876
|
-
return config.enabled;
|
|
5877
|
-
}
|
|
5878
|
-
|
|
5879
|
-
// src/channels/lark/mapping-service.ts
|
|
5880
|
-
var import_crypto6 = require("crypto");
|
|
5881
|
-
function createChannelThreadMappingService(deps) {
|
|
5882
|
-
return {
|
|
5883
|
-
async getOrCreateThread(input) {
|
|
5884
|
-
const externalSubjectKey = buildExternalSubjectKey(input);
|
|
5885
|
-
const existing = await deps.mappingStore.getMappingBySubject({
|
|
5886
|
-
channel: input.channel,
|
|
5887
|
-
channelAppId: input.channelAppId,
|
|
5888
|
-
tenantId: input.tenantId,
|
|
5889
|
-
assistantId: input.assistantId,
|
|
5890
|
-
externalSubjectKey
|
|
5891
|
-
});
|
|
5892
|
-
if (existing) {
|
|
5893
|
-
return { threadId: existing.threadId };
|
|
5894
|
-
}
|
|
5895
|
-
const threadId = (deps.uuid || import_crypto6.randomUUID)();
|
|
5896
|
-
await deps.threadStore.createThread(input.tenantId, input.assistantId, threadId, {
|
|
5806
|
+
var larkChannelAdapter = {
|
|
5807
|
+
channel: "lark",
|
|
5808
|
+
configSchema: larkConfigSchema,
|
|
5809
|
+
async receive(rawPayload, installation) {
|
|
5810
|
+
const event = parseLarkMessageEvent(rawPayload);
|
|
5811
|
+
if (!event) return null;
|
|
5812
|
+
return {
|
|
5813
|
+
channel: "lark",
|
|
5814
|
+
channelInstallationId: installation.id,
|
|
5815
|
+
tenantId: installation.tenantId,
|
|
5816
|
+
sender: {
|
|
5817
|
+
id: event.openId,
|
|
5818
|
+
displayName: void 0
|
|
5819
|
+
},
|
|
5820
|
+
content: {
|
|
5821
|
+
text: event.text,
|
|
5897
5822
|
metadata: {
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
channel: input.channel,
|
|
5902
|
-
larkChatId: input.chatId,
|
|
5903
|
-
larkOpenId: input.openId
|
|
5904
|
-
}
|
|
5905
|
-
});
|
|
5906
|
-
try {
|
|
5907
|
-
await deps.mappingStore.createMapping({
|
|
5908
|
-
channel: input.channel,
|
|
5909
|
-
channelAppId: input.channelAppId,
|
|
5910
|
-
tenantId: input.tenantId,
|
|
5911
|
-
assistantId: input.assistantId,
|
|
5912
|
-
mappingMode: input.mappingMode,
|
|
5913
|
-
externalSubjectType: resolveSubjectType(input.mappingMode, input.chatType) === "user" ? "user" : "chat",
|
|
5914
|
-
externalSubjectKey,
|
|
5915
|
-
larkOpenId: input.openId,
|
|
5916
|
-
larkChatId: input.chatId,
|
|
5917
|
-
larkMessageId: input.messageId,
|
|
5918
|
-
threadId
|
|
5919
|
-
});
|
|
5920
|
-
} catch (error) {
|
|
5921
|
-
if (!isUniqueViolation(error)) {
|
|
5922
|
-
throw error;
|
|
5823
|
+
chatId: event.chatId,
|
|
5824
|
+
chatType: event.chatType,
|
|
5825
|
+
messageId: event.messageId
|
|
5923
5826
|
}
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
|
|
5932
|
-
|
|
5827
|
+
},
|
|
5828
|
+
conversation: {
|
|
5829
|
+
id: event.chatId,
|
|
5830
|
+
type: event.chatType
|
|
5831
|
+
},
|
|
5832
|
+
replyTarget: {
|
|
5833
|
+
adapterChannel: "lark",
|
|
5834
|
+
channelInstallationId: installation.id,
|
|
5835
|
+
rawTarget: {
|
|
5836
|
+
chatId: event.chatId,
|
|
5837
|
+
messageId: event.messageId,
|
|
5838
|
+
chatType: event.chatType
|
|
5933
5839
|
}
|
|
5934
|
-
await deps.threadStore.deleteThread(input.tenantId, threadId);
|
|
5935
|
-
return { threadId: canonical.threadId };
|
|
5936
5840
|
}
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
}
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
const subjectValue = subjectType === "user" ? input.openId : input.chatId;
|
|
5947
|
-
return [
|
|
5948
|
-
input.channel,
|
|
5949
|
-
input.channelAppId,
|
|
5950
|
-
`tenant:${input.tenantId}`,
|
|
5951
|
-
`assistant:${input.assistantId}`,
|
|
5952
|
-
`${subjectType}:${subjectValue}`
|
|
5953
|
-
].join(":");
|
|
5954
|
-
}
|
|
5955
|
-
function resolveSubjectType(mappingMode, chatType) {
|
|
5956
|
-
if (mappingMode === "user") {
|
|
5957
|
-
return "user";
|
|
5958
|
-
}
|
|
5959
|
-
if (mappingMode === "group") {
|
|
5960
|
-
return "chat";
|
|
5961
|
-
}
|
|
5962
|
-
return chatType === "direct" ? "user" : "chat";
|
|
5963
|
-
}
|
|
5964
|
-
|
|
5965
|
-
// src/channels/lark/runner.ts
|
|
5966
|
-
var import_core28 = require("@axiom-lattice/core");
|
|
5967
|
-
var import_protocols5 = require("@axiom-lattice/protocols");
|
|
5968
|
-
|
|
5969
|
-
// src/channels/lark/aggregator.ts
|
|
5970
|
-
var import_protocols4 = require("@axiom-lattice/protocols");
|
|
5971
|
-
function aggregateLarkReply(messageId, chunks) {
|
|
5972
|
-
return chunks.filter(
|
|
5973
|
-
(chunk) => chunk.type === import_protocols4.MessageChunkTypes.AI && chunk.data.id === messageId
|
|
5974
|
-
).map((chunk) => chunk.data.content || "").join("").trim();
|
|
5975
|
-
}
|
|
5976
|
-
|
|
5977
|
-
// src/channels/lark/runner.ts
|
|
5978
|
-
async function runAgentAndCollectLarkReply(input) {
|
|
5979
|
-
const agent = import_core28.agentInstanceManager.getAgent({
|
|
5980
|
-
tenant_id: input.tenantId,
|
|
5981
|
-
assistant_id: input.assistantId,
|
|
5982
|
-
thread_id: input.threadId,
|
|
5983
|
-
workspace_id: input.workspaceId,
|
|
5984
|
-
project_id: input.projectId
|
|
5985
|
-
});
|
|
5986
|
-
const result = await agent.addMessage({
|
|
5987
|
-
input: {
|
|
5988
|
-
message: input.text
|
|
5989
|
-
}
|
|
5990
|
-
});
|
|
5991
|
-
const chunks = [];
|
|
5992
|
-
const stream = agent.chunkStream(result.messageId, [
|
|
5993
|
-
import_protocols5.MessageChunkTypes.MESSAGE_COMPLETED
|
|
5994
|
-
]);
|
|
5995
|
-
for await (const chunk of stream) {
|
|
5996
|
-
chunks.push(chunk);
|
|
5841
|
+
};
|
|
5842
|
+
},
|
|
5843
|
+
async sendReply(replyTarget, message, installation) {
|
|
5844
|
+
const { createLarkSender: createLarkSender2 } = await Promise.resolve().then(() => (init_sender(), sender_exports));
|
|
5845
|
+
const sender = createLarkSender2(installation.config);
|
|
5846
|
+
await sender.sendTextReply({
|
|
5847
|
+
chatId: replyTarget.rawTarget.chatId,
|
|
5848
|
+
text: message.text
|
|
5849
|
+
});
|
|
5997
5850
|
}
|
|
5998
|
-
|
|
5999
|
-
}
|
|
6000
|
-
|
|
6001
|
-
// src/channels/lark/sender.ts
|
|
6002
|
-
async function createLarkSender(config, client) {
|
|
6003
|
-
const resolved = client ?? await createDefaultLarkClient(config);
|
|
6004
|
-
return {
|
|
6005
|
-
async sendTextReply(input) {
|
|
6006
|
-
const response = await resolved.im.v1.message.create({
|
|
6007
|
-
params: {
|
|
6008
|
-
receive_id_type: "chat_id"
|
|
6009
|
-
},
|
|
6010
|
-
data: {
|
|
6011
|
-
receive_id: input.chatId,
|
|
6012
|
-
msg_type: "text",
|
|
6013
|
-
content: JSON.stringify({ text: input.text })
|
|
6014
|
-
}
|
|
6015
|
-
});
|
|
6016
|
-
if (response.code && response.code !== 0) {
|
|
6017
|
-
throw new Error("Failed to send Lark reply");
|
|
6018
|
-
}
|
|
6019
|
-
}
|
|
6020
|
-
};
|
|
6021
|
-
}
|
|
6022
|
-
async function createDefaultLarkClient(config) {
|
|
6023
|
-
const Lark = await import("@larksuiteoapi/node-sdk");
|
|
6024
|
-
return new Lark.Client({
|
|
6025
|
-
appId: config.appId,
|
|
6026
|
-
appSecret: config.appSecret
|
|
6027
|
-
});
|
|
6028
|
-
}
|
|
5851
|
+
};
|
|
6029
5852
|
|
|
6030
5853
|
// src/channels/lark/verification.ts
|
|
6031
|
-
var
|
|
5854
|
+
var import_crypto6 = __toESM(require("crypto"));
|
|
6032
5855
|
function parseLarkRequestBody(body, encryptKey) {
|
|
6033
5856
|
const parsed = body || {};
|
|
6034
5857
|
if (encryptKey && typeof parsed.encrypt === "string") {
|
|
@@ -6037,138 +5860,210 @@ function parseLarkRequestBody(body, encryptKey) {
|
|
|
6037
5860
|
return parsed;
|
|
6038
5861
|
}
|
|
6039
5862
|
function decryptLarkPayload(encryptKey, encryptedPayload) {
|
|
6040
|
-
const key =
|
|
5863
|
+
const key = import_crypto6.default.createHash("sha256").update(encryptKey).digest();
|
|
6041
5864
|
const buffer = Buffer.from(encryptedPayload, "base64");
|
|
6042
5865
|
const iv = buffer.subarray(0, 16);
|
|
6043
5866
|
const ciphertext = buffer.subarray(16);
|
|
6044
|
-
const decipher =
|
|
5867
|
+
const decipher = import_crypto6.default.createDecipheriv("aes-256-cbc", key, iv);
|
|
6045
5868
|
const plaintext = Buffer.concat([
|
|
6046
5869
|
decipher.update(ciphertext),
|
|
6047
5870
|
decipher.final()
|
|
6048
5871
|
]).toString("utf8");
|
|
6049
5872
|
return JSON.parse(plaintext);
|
|
6050
5873
|
}
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
5874
|
+
|
|
5875
|
+
// src/logger/Logger.ts
|
|
5876
|
+
var import_pino = __toESM(require("pino"));
|
|
5877
|
+
var import_pino_pretty = require("pino-pretty");
|
|
5878
|
+
var import_pino_roll = require("pino-roll");
|
|
5879
|
+
var PinoLoggerFactory = class _PinoLoggerFactory {
|
|
5880
|
+
constructor() {
|
|
5881
|
+
const isProd = process.env.NODE_ENV === "production";
|
|
5882
|
+
const loggerConfig = {
|
|
5883
|
+
// 自定义时间戳格式
|
|
5884
|
+
timestamp: () => `,"@timestamp":"${(/* @__PURE__ */ new Date()).toISOString()}"`,
|
|
5885
|
+
// 关闭默认的时间戳键
|
|
5886
|
+
base: {
|
|
5887
|
+
"@version": "1",
|
|
5888
|
+
app_name: "lattice",
|
|
5889
|
+
service_name: "lattice/graph-server",
|
|
5890
|
+
thread_name: "main",
|
|
5891
|
+
logger_name: "lattice-graph-logger"
|
|
5892
|
+
},
|
|
5893
|
+
formatters: {
|
|
5894
|
+
level: (label, number) => {
|
|
5895
|
+
return {
|
|
5896
|
+
level: label.toUpperCase(),
|
|
5897
|
+
level_value: number * 1e3
|
|
5898
|
+
};
|
|
5899
|
+
}
|
|
5900
|
+
}
|
|
5901
|
+
};
|
|
5902
|
+
if (isProd) {
|
|
5903
|
+
try {
|
|
5904
|
+
this.pinoLogger = (0, import_pino.default)(
|
|
5905
|
+
loggerConfig,
|
|
5906
|
+
import_pino.default.transport({
|
|
5907
|
+
target: "pino-roll",
|
|
5908
|
+
options: {
|
|
5909
|
+
file: "./logs/fin_ai_graph_server",
|
|
5910
|
+
frequency: "daily",
|
|
5911
|
+
mkdir: true
|
|
5912
|
+
}
|
|
5913
|
+
})
|
|
5914
|
+
);
|
|
5915
|
+
} catch (error) {
|
|
5916
|
+
console.error(
|
|
5917
|
+
"\u65E0\u6CD5\u521D\u59CB\u5316 pino-roll \u65E5\u5FD7\u8BB0\u5F55\u5668\uFF0C\u56DE\u9000\u5230\u63A7\u5236\u53F0\u65E5\u5FD7",
|
|
5918
|
+
error
|
|
5919
|
+
);
|
|
5920
|
+
this.pinoLogger = (0, import_pino.default)({
|
|
5921
|
+
...loggerConfig,
|
|
5922
|
+
transport: {
|
|
5923
|
+
target: "pino-pretty",
|
|
5924
|
+
options: {
|
|
5925
|
+
colorize: true
|
|
5926
|
+
}
|
|
5927
|
+
}
|
|
5928
|
+
});
|
|
5929
|
+
}
|
|
5930
|
+
} else {
|
|
5931
|
+
this.pinoLogger = (0, import_pino.default)({
|
|
5932
|
+
...loggerConfig,
|
|
5933
|
+
transport: {
|
|
5934
|
+
target: "pino-pretty",
|
|
5935
|
+
options: {
|
|
5936
|
+
colorize: true
|
|
5937
|
+
}
|
|
5938
|
+
}
|
|
5939
|
+
});
|
|
5940
|
+
}
|
|
6060
5941
|
}
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
|
|
6065
|
-
return
|
|
5942
|
+
static getInstance() {
|
|
5943
|
+
if (!_PinoLoggerFactory.instance) {
|
|
5944
|
+
_PinoLoggerFactory.instance = new _PinoLoggerFactory();
|
|
5945
|
+
}
|
|
5946
|
+
return _PinoLoggerFactory.instance;
|
|
5947
|
+
}
|
|
5948
|
+
getPinoLogger() {
|
|
5949
|
+
return this.pinoLogger;
|
|
5950
|
+
}
|
|
5951
|
+
};
|
|
5952
|
+
var Logger = class _Logger {
|
|
5953
|
+
constructor(options) {
|
|
5954
|
+
this.context = options?.context || {};
|
|
5955
|
+
this.name = options?.name || "lattice-graph-logger";
|
|
5956
|
+
this.serviceName = options?.serviceName || "lattice/graph-server";
|
|
5957
|
+
}
|
|
5958
|
+
/**
|
|
5959
|
+
* 获取合并了上下文的日志对象
|
|
5960
|
+
* @param additionalContext 额外的上下文数据
|
|
5961
|
+
* @returns 带有上下文的pino日志对象
|
|
5962
|
+
*/
|
|
5963
|
+
getContextualLogger(additionalContext) {
|
|
5964
|
+
const pinoLogger = PinoLoggerFactory.getInstance().getPinoLogger();
|
|
5965
|
+
const contextObj = {
|
|
5966
|
+
"x-user-id": this.context["x-user-id"] || "",
|
|
5967
|
+
"x-tenant-id": this.context["x-tenant-id"] || "",
|
|
5968
|
+
"x-request-id": this.context["x-request-id"] || "",
|
|
5969
|
+
"x-task-id": this.context["x-task-id"] || "",
|
|
5970
|
+
"x-thread-id": this.context["x-thread-id"] || "",
|
|
5971
|
+
service_name: this.serviceName,
|
|
5972
|
+
logger_name: this.name,
|
|
5973
|
+
...additionalContext
|
|
5974
|
+
};
|
|
5975
|
+
return pinoLogger.child(contextObj);
|
|
5976
|
+
}
|
|
5977
|
+
info(msg, obj) {
|
|
5978
|
+
this.getContextualLogger(obj).info(msg);
|
|
6066
5979
|
}
|
|
6067
|
-
|
|
6068
|
-
|
|
5980
|
+
error(msg, obj) {
|
|
5981
|
+
this.getContextualLogger(obj).error(msg);
|
|
6069
5982
|
}
|
|
6070
|
-
|
|
5983
|
+
warn(msg, obj) {
|
|
5984
|
+
this.getContextualLogger(obj).warn(msg);
|
|
5985
|
+
}
|
|
5986
|
+
debug(msg, obj) {
|
|
5987
|
+
this.getContextualLogger(obj).debug(msg);
|
|
5988
|
+
}
|
|
5989
|
+
/**
|
|
5990
|
+
* 更新Logger实例的上下文
|
|
5991
|
+
*/
|
|
5992
|
+
updateContext(context) {
|
|
5993
|
+
this.context = {
|
|
5994
|
+
...this.context,
|
|
5995
|
+
...context
|
|
5996
|
+
};
|
|
5997
|
+
}
|
|
5998
|
+
/**
|
|
5999
|
+
* 创建一个新的Logger实例,继承当前Logger的上下文
|
|
6000
|
+
*/
|
|
6001
|
+
child(options) {
|
|
6002
|
+
return new _Logger({
|
|
6003
|
+
name: options.name || this.name,
|
|
6004
|
+
serviceName: options.serviceName || this.serviceName,
|
|
6005
|
+
context: {
|
|
6006
|
+
...this.context,
|
|
6007
|
+
...options.context
|
|
6008
|
+
}
|
|
6009
|
+
});
|
|
6010
|
+
}
|
|
6011
|
+
};
|
|
6012
|
+
|
|
6013
|
+
// src/channels/lark/controller.ts
|
|
6014
|
+
var logger = new Logger({ serviceName: "lattice/gateway/lark" });
|
|
6015
|
+
function createLarkEventHandler(deps) {
|
|
6016
|
+
return async function handleLarkEvent(request, reply) {
|
|
6017
|
+
const { installationId } = request.params;
|
|
6018
|
+
const installation = await deps.installationStore.getInstallationById(installationId);
|
|
6019
|
+
if (!installation || installation.channel !== "lark") {
|
|
6020
|
+
reply.status(404).send({ success: false, message: "Installation not found" });
|
|
6021
|
+
return;
|
|
6022
|
+
}
|
|
6023
|
+
const body = parseLarkRequestBody(request.body, installation.config.encryptKey);
|
|
6024
|
+
if (body.type === "url_verification" && body.challenge) {
|
|
6025
|
+
reply.status(200).send({ challenge: body.challenge });
|
|
6026
|
+
return;
|
|
6027
|
+
}
|
|
6028
|
+
const inboundMessage = await larkChannelAdapter.receive(request.body, installation);
|
|
6029
|
+
if (!inboundMessage) {
|
|
6030
|
+
reply.status(200).send();
|
|
6031
|
+
return;
|
|
6032
|
+
}
|
|
6033
|
+
deps.router.dispatch(inboundMessage).catch((error) => {
|
|
6034
|
+
logger.error("Lark message dispatch error", {
|
|
6035
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6036
|
+
});
|
|
6037
|
+
});
|
|
6038
|
+
reply.status(200).send();
|
|
6039
|
+
};
|
|
6071
6040
|
}
|
|
6072
6041
|
|
|
6073
6042
|
// src/channels/lark/routes.ts
|
|
6074
|
-
function registerLarkChannelRoutes(app2,
|
|
6075
|
-
const
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
}
|
|
6079
|
-
const handlerDependencies = dependencies || createDefaultLarkDependencies();
|
|
6043
|
+
function registerLarkChannelRoutes(app2, deps) {
|
|
6044
|
+
const handler = createLarkEventHandler({
|
|
6045
|
+
installationStore: deps.installationStore,
|
|
6046
|
+
router: deps.router
|
|
6047
|
+
});
|
|
6080
6048
|
app2.post(
|
|
6081
6049
|
"/api/channels/lark/installations/:installationId/events",
|
|
6082
|
-
|
|
6083
|
-
...handlerDependencies
|
|
6084
|
-
})
|
|
6050
|
+
handler
|
|
6085
6051
|
);
|
|
6086
6052
|
}
|
|
6087
|
-
function createDefaultLarkDependencies() {
|
|
6088
|
-
const installationStore = new import_pg_stores.PostgreSQLChannelInstallationStore({
|
|
6089
|
-
poolConfig: getDatabaseUrl()
|
|
6090
|
-
});
|
|
6091
|
-
const threadStore = (0, import_core29.getStoreLattice)("default", "thread").store;
|
|
6092
|
-
const mappingStore = new import_pg_stores.ChannelIdentityMappingStore({
|
|
6093
|
-
poolConfig: getDatabaseUrl()
|
|
6094
|
-
});
|
|
6095
|
-
const mappingService = createChannelThreadMappingService({
|
|
6096
|
-
mappingStore,
|
|
6097
|
-
threadStore
|
|
6098
|
-
});
|
|
6099
|
-
return {
|
|
6100
|
-
getInstallationConfig: async (installationId) => {
|
|
6101
|
-
const installation = await installationStore.getInstallationById(
|
|
6102
|
-
installationId
|
|
6103
|
-
);
|
|
6104
|
-
if (!installation || installation.channel !== "lark") {
|
|
6105
|
-
return null;
|
|
6106
|
-
}
|
|
6107
|
-
return {
|
|
6108
|
-
enabled: true,
|
|
6109
|
-
installationId: installation.id,
|
|
6110
|
-
tenantId: installation.tenantId,
|
|
6111
|
-
assistantId: installation.config.assistantId,
|
|
6112
|
-
appId: installation.config.appId,
|
|
6113
|
-
appSecret: installation.config.appSecret,
|
|
6114
|
-
verificationToken: installation.config.verificationToken,
|
|
6115
|
-
encryptKey: installation.config.encryptKey,
|
|
6116
|
-
workspaceId: installation.config.workspaceId,
|
|
6117
|
-
projectId: installation.config.projectId,
|
|
6118
|
-
mappingMode: installation.config.mappingMode
|
|
6119
|
-
};
|
|
6120
|
-
},
|
|
6121
|
-
parseRequestBody: (body, encryptKey) => parseLarkRequestBody(body, encryptKey),
|
|
6122
|
-
verifyParsedBody: (body, config) => {
|
|
6123
|
-
if (!config.verificationToken) {
|
|
6124
|
-
return true;
|
|
6125
|
-
}
|
|
6126
|
-
return createLarkRequestVerifier(config)({
|
|
6127
|
-
body
|
|
6128
|
-
});
|
|
6129
|
-
},
|
|
6130
|
-
parseEvent: parseLarkMessageEvent,
|
|
6131
|
-
claimInboundReceipt: (input) => mappingStore.claimInboundReceipt(input),
|
|
6132
|
-
markInboundReceiptCompleted: (input) => mappingStore.markInboundReceiptCompleted(input),
|
|
6133
|
-
markInboundReceiptFailed: (input) => mappingStore.markInboundReceiptFailed(input),
|
|
6134
|
-
resolveThread: (input) => mappingService.getOrCreateThread(input),
|
|
6135
|
-
runAgentAndCollectText: ({ tenantId, assistantId, threadId, text, workspaceId, projectId }) => runAgentAndCollectLarkReply({
|
|
6136
|
-
tenantId,
|
|
6137
|
-
assistantId,
|
|
6138
|
-
threadId,
|
|
6139
|
-
text,
|
|
6140
|
-
workspaceId,
|
|
6141
|
-
projectId
|
|
6142
|
-
}),
|
|
6143
|
-
sendTextReply: async ({ chatId, text, config }) => {
|
|
6144
|
-
const sender = await createLarkSender({
|
|
6145
|
-
appId: config.appId,
|
|
6146
|
-
appSecret: config.appSecret
|
|
6147
|
-
});
|
|
6148
|
-
await sender.sendTextReply({ chatId, text });
|
|
6149
|
-
}
|
|
6150
|
-
};
|
|
6151
|
-
}
|
|
6152
|
-
function getDatabaseUrl() {
|
|
6153
|
-
const databaseUrl = process.env.DATABASE_URL;
|
|
6154
|
-
if (!databaseUrl) {
|
|
6155
|
-
throw new Error("DATABASE_URL is required for Lark channel ingress");
|
|
6156
|
-
}
|
|
6157
|
-
return databaseUrl;
|
|
6158
|
-
}
|
|
6159
6053
|
|
|
6160
6054
|
// src/channels/routes.ts
|
|
6161
6055
|
var channelRouteRegistrars = [
|
|
6162
|
-
(app2,
|
|
6056
|
+
(app2, deps) => registerLarkChannelRoutes(app2, deps)
|
|
6163
6057
|
];
|
|
6164
|
-
function registerChannelRoutes(app2, dependencies
|
|
6058
|
+
function registerChannelRoutes(app2, dependencies) {
|
|
6059
|
+
if (!dependencies) return;
|
|
6165
6060
|
for (const registerRoutes of channelRouteRegistrars) {
|
|
6166
6061
|
registerRoutes(app2, dependencies);
|
|
6167
6062
|
}
|
|
6168
6063
|
}
|
|
6169
6064
|
|
|
6170
6065
|
// src/controllers/channel-installations.ts
|
|
6171
|
-
var
|
|
6066
|
+
var import_crypto7 = require("crypto");
|
|
6172
6067
|
function getTenantId11(request) {
|
|
6173
6068
|
const userTenantId = request.user?.tenantId;
|
|
6174
6069
|
if (userTenantId) {
|
|
@@ -6177,12 +6072,15 @@ function getTenantId11(request) {
|
|
|
6177
6072
|
return request.headers["x-tenant-id"] || "default";
|
|
6178
6073
|
}
|
|
6179
6074
|
async function getInstallationStore() {
|
|
6180
|
-
const {
|
|
6075
|
+
const { getStoreLattice: getStoreLattice16 } = await import("@axiom-lattice/core");
|
|
6076
|
+
const store = getStoreLattice16("default", "channelInstallation").store;
|
|
6077
|
+
if (store) return store;
|
|
6078
|
+
const { PostgreSQLChannelInstallationStore } = await import("@axiom-lattice/pg-stores");
|
|
6181
6079
|
const databaseUrl = process.env.DATABASE_URL;
|
|
6182
6080
|
if (!databaseUrl) {
|
|
6183
6081
|
throw new Error("DATABASE_URL is required for channel installation store");
|
|
6184
6082
|
}
|
|
6185
|
-
return new
|
|
6083
|
+
return new PostgreSQLChannelInstallationStore({
|
|
6186
6084
|
poolConfig: databaseUrl
|
|
6187
6085
|
});
|
|
6188
6086
|
}
|
|
@@ -6281,7 +6179,7 @@ async function createChannelInstallation(request, reply) {
|
|
|
6281
6179
|
}
|
|
6282
6180
|
}
|
|
6283
6181
|
const store = await getInstallationStore();
|
|
6284
|
-
const installationId = body.id || (0,
|
|
6182
|
+
const installationId = body.id || (0, import_crypto7.randomUUID)();
|
|
6285
6183
|
const installation = await store.createInstallation(
|
|
6286
6184
|
tenantId,
|
|
6287
6185
|
installationId,
|
|
@@ -6404,8 +6302,129 @@ function registerChannelInstallationRoutes(app2) {
|
|
|
6404
6302
|
app2.delete("/api/channel-installations/:installationId", deleteChannelInstallation);
|
|
6405
6303
|
}
|
|
6406
6304
|
|
|
6305
|
+
// src/bindings/index.ts
|
|
6306
|
+
var registryInstance = null;
|
|
6307
|
+
function setBindingRegistry(registry) {
|
|
6308
|
+
registryInstance = registry;
|
|
6309
|
+
}
|
|
6310
|
+
function getBindingRegistry() {
|
|
6311
|
+
if (!registryInstance) {
|
|
6312
|
+
throw new Error("BindingRegistry not initialized. Call setBindingRegistry() first.");
|
|
6313
|
+
}
|
|
6314
|
+
return registryInstance;
|
|
6315
|
+
}
|
|
6316
|
+
|
|
6317
|
+
// src/controllers/channel-bindings.ts
|
|
6318
|
+
function getTenantId12(request) {
|
|
6319
|
+
const userTenantId = request.user?.tenantId;
|
|
6320
|
+
if (userTenantId) return userTenantId;
|
|
6321
|
+
return request.headers["x-tenant-id"] || "default";
|
|
6322
|
+
}
|
|
6323
|
+
async function getBindingList(request, _reply) {
|
|
6324
|
+
const tenantId = getTenantId12(request);
|
|
6325
|
+
const { channel, agentId, channelInstallationId, limit, offset } = request.query;
|
|
6326
|
+
try {
|
|
6327
|
+
const registry = getBindingRegistry();
|
|
6328
|
+
const bindings = await registry.list({ channel, agentId, tenantId, channelInstallationId, limit, offset });
|
|
6329
|
+
return { success: true, message: "Bindings retrieved", data: { records: bindings, total: bindings.length } };
|
|
6330
|
+
} catch (error) {
|
|
6331
|
+
console.error("Failed to get bindings:", error);
|
|
6332
|
+
return { success: false, message: "Failed to retrieve bindings", data: { records: [], total: 0 } };
|
|
6333
|
+
}
|
|
6334
|
+
}
|
|
6335
|
+
async function getBinding(request, reply) {
|
|
6336
|
+
const tenantId = getTenantId12(request);
|
|
6337
|
+
try {
|
|
6338
|
+
const registry = getBindingRegistry();
|
|
6339
|
+
const bindings = await registry.list({ tenantId });
|
|
6340
|
+
const binding = bindings.find((b) => b.id === request.params.id);
|
|
6341
|
+
if (!binding || binding.tenantId !== tenantId) {
|
|
6342
|
+
reply.status(404);
|
|
6343
|
+
return { success: false, message: "Binding not found" };
|
|
6344
|
+
}
|
|
6345
|
+
return { success: true, message: "Binding retrieved", data: binding };
|
|
6346
|
+
} catch (error) {
|
|
6347
|
+
console.error("Failed to get binding:", error);
|
|
6348
|
+
return { success: false, message: "Failed to retrieve binding" };
|
|
6349
|
+
}
|
|
6350
|
+
}
|
|
6351
|
+
async function createBinding(request, reply) {
|
|
6352
|
+
const tenantId = getTenantId12(request);
|
|
6353
|
+
try {
|
|
6354
|
+
const registry = getBindingRegistry();
|
|
6355
|
+
const binding = await registry.create({ ...request.body, tenantId });
|
|
6356
|
+
reply.status(201);
|
|
6357
|
+
return { success: true, message: "Binding created", data: binding };
|
|
6358
|
+
} catch (error) {
|
|
6359
|
+
console.error("Failed to create binding:", error);
|
|
6360
|
+
reply.status(500);
|
|
6361
|
+
return { success: false, message: "Failed to create binding" };
|
|
6362
|
+
}
|
|
6363
|
+
}
|
|
6364
|
+
async function updateBinding(request, reply) {
|
|
6365
|
+
try {
|
|
6366
|
+
const tenantId = getTenantId12(request);
|
|
6367
|
+
const registry = getBindingRegistry();
|
|
6368
|
+
const bindings = await registry.list({ tenantId });
|
|
6369
|
+
const existing = bindings.find((b) => b.id === request.params.id);
|
|
6370
|
+
if (!existing || existing.tenantId !== tenantId) {
|
|
6371
|
+
reply.status(404);
|
|
6372
|
+
return { success: false, message: "Binding not found" };
|
|
6373
|
+
}
|
|
6374
|
+
const binding = await registry.update(request.params.id, request.body);
|
|
6375
|
+
return { success: true, message: "Binding updated", data: binding };
|
|
6376
|
+
} catch (error) {
|
|
6377
|
+
console.error("Failed to update binding:", error);
|
|
6378
|
+
reply.status(500);
|
|
6379
|
+
return { success: false, message: "Failed to update binding" };
|
|
6380
|
+
}
|
|
6381
|
+
}
|
|
6382
|
+
async function deleteBinding(request, reply) {
|
|
6383
|
+
try {
|
|
6384
|
+
const tenantId = getTenantId12(request);
|
|
6385
|
+
const registry = getBindingRegistry();
|
|
6386
|
+
const bindings = await registry.list({ tenantId });
|
|
6387
|
+
const existing = bindings.find((b) => b.id === request.params.id);
|
|
6388
|
+
if (!existing || existing.tenantId !== tenantId) {
|
|
6389
|
+
reply.status(404);
|
|
6390
|
+
return { success: false, message: "Binding not found" };
|
|
6391
|
+
}
|
|
6392
|
+
await registry.delete(request.params.id);
|
|
6393
|
+
return { success: true, message: "Binding deleted" };
|
|
6394
|
+
} catch (error) {
|
|
6395
|
+
console.error("Failed to delete binding:", error);
|
|
6396
|
+
reply.status(500);
|
|
6397
|
+
return { success: false, message: "Failed to delete binding" };
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
async function resolveBinding(request, _reply) {
|
|
6401
|
+
const tenantId = getTenantId12(request);
|
|
6402
|
+
const { channel, senderId, channelInstallationId } = request.query;
|
|
6403
|
+
try {
|
|
6404
|
+
const registry = getBindingRegistry();
|
|
6405
|
+
const binding = await registry.resolve({ channel, senderId, channelInstallationId, tenantId });
|
|
6406
|
+
if (!binding) {
|
|
6407
|
+
return { success: false, message: "No binding found", data: null };
|
|
6408
|
+
}
|
|
6409
|
+
return { success: true, message: "Binding found", data: binding };
|
|
6410
|
+
} catch (error) {
|
|
6411
|
+
console.error("Failed to resolve binding:", error);
|
|
6412
|
+
return { success: false, message: "Failed to resolve binding", data: null };
|
|
6413
|
+
}
|
|
6414
|
+
}
|
|
6415
|
+
|
|
6416
|
+
// src/routes/channel-bindings.ts
|
|
6417
|
+
function registerChannelBindingRoutes(app2) {
|
|
6418
|
+
app2.get("/api/channel-bindings", getBindingList);
|
|
6419
|
+
app2.get("/api/channel-bindings/resolve", resolveBinding);
|
|
6420
|
+
app2.post("/api/channel-bindings", createBinding);
|
|
6421
|
+
app2.get("/api/channel-bindings/:id", getBinding);
|
|
6422
|
+
app2.put("/api/channel-bindings/:id", updateBinding);
|
|
6423
|
+
app2.delete("/api/channel-bindings/:id", deleteBinding);
|
|
6424
|
+
}
|
|
6425
|
+
|
|
6407
6426
|
// src/routes/index.ts
|
|
6408
|
-
var registerLatticeRoutes = (app2) => {
|
|
6427
|
+
var registerLatticeRoutes = (app2, channelDeps) => {
|
|
6409
6428
|
app2.post("/api/runs", createRun);
|
|
6410
6429
|
app2.post("/api/resume_stream", resumeStream);
|
|
6411
6430
|
app2.post("/api/assistants/:assistantId/threads/:threadId/abort", abortRun);
|
|
@@ -6540,8 +6559,46 @@ var registerLatticeRoutes = (app2) => {
|
|
|
6540
6559
|
autoApproveUsers: process.env.AUTO_APPROVE_USERS !== "false",
|
|
6541
6560
|
allowTenantRegistration: process.env.ALLOW_TENANT_REGISTRATION !== "false"
|
|
6542
6561
|
});
|
|
6543
|
-
registerChannelRoutes(app2);
|
|
6562
|
+
registerChannelRoutes(app2, channelDeps);
|
|
6544
6563
|
registerChannelInstallationRoutes(app2);
|
|
6564
|
+
if (channelDeps) {
|
|
6565
|
+
registerChannelBindingRoutes(app2);
|
|
6566
|
+
}
|
|
6567
|
+
if (channelDeps?.router) {
|
|
6568
|
+
app2.post("/api/channels/inbound", async (request, reply) => {
|
|
6569
|
+
try {
|
|
6570
|
+
const router = channelDeps.router;
|
|
6571
|
+
const msg = request.body;
|
|
6572
|
+
if (!msg.channel || !msg.sender || !msg.content) {
|
|
6573
|
+
reply.status(400).send({
|
|
6574
|
+
success: false,
|
|
6575
|
+
message: "Missing required fields: channel, sender, content"
|
|
6576
|
+
});
|
|
6577
|
+
return;
|
|
6578
|
+
}
|
|
6579
|
+
const inboundMessage = {
|
|
6580
|
+
channel: msg.channel,
|
|
6581
|
+
channelInstallationId: msg.channelInstallationId || "",
|
|
6582
|
+
tenantId: msg.tenantId || "default",
|
|
6583
|
+
sender: {
|
|
6584
|
+
id: msg.sender.id,
|
|
6585
|
+
displayName: msg.sender.displayName
|
|
6586
|
+
},
|
|
6587
|
+
content: {
|
|
6588
|
+
text: msg.content.text
|
|
6589
|
+
},
|
|
6590
|
+
replyTarget: msg.replyTarget
|
|
6591
|
+
};
|
|
6592
|
+
await router.dispatch(inboundMessage).catch((error) => {
|
|
6593
|
+
console.error("Inbound dispatch error:", error);
|
|
6594
|
+
});
|
|
6595
|
+
reply.status(200).send({ accepted: true });
|
|
6596
|
+
} catch (error) {
|
|
6597
|
+
console.error("Inbound route error:", error);
|
|
6598
|
+
reply.status(500).send({ success: false, message: "Internal error" });
|
|
6599
|
+
}
|
|
6600
|
+
});
|
|
6601
|
+
}
|
|
6545
6602
|
app2.get(
|
|
6546
6603
|
"/api/workflows/definitions",
|
|
6547
6604
|
getAllWorkflowDefinitions
|
|
@@ -6572,6 +6629,267 @@ var registerLatticeRoutes = (app2) => {
|
|
|
6572
6629
|
);
|
|
6573
6630
|
};
|
|
6574
6631
|
|
|
6632
|
+
// src/router/MessageRouter.ts
|
|
6633
|
+
var import_core28 = require("@axiom-lattice/core");
|
|
6634
|
+
var import_crypto8 = require("crypto");
|
|
6635
|
+
var BindingNotFoundError = class extends Error {
|
|
6636
|
+
constructor(message) {
|
|
6637
|
+
super(message);
|
|
6638
|
+
this.name = "BindingNotFoundError";
|
|
6639
|
+
}
|
|
6640
|
+
};
|
|
6641
|
+
var MessageRouter = class {
|
|
6642
|
+
constructor(config) {
|
|
6643
|
+
this.middlewares = [...config.middlewares];
|
|
6644
|
+
this.bindingRegistry = config.bindingRegistry;
|
|
6645
|
+
this.adapterRegistry = config.adapterRegistry;
|
|
6646
|
+
this.installationStore = config.installationStore;
|
|
6647
|
+
}
|
|
6648
|
+
use(middleware) {
|
|
6649
|
+
this.middlewares.push(middleware);
|
|
6650
|
+
}
|
|
6651
|
+
async dispatch(message) {
|
|
6652
|
+
const ctx = {
|
|
6653
|
+
inboundMessage: message,
|
|
6654
|
+
metadata: {}
|
|
6655
|
+
};
|
|
6656
|
+
try {
|
|
6657
|
+
await this.runMiddlewares(ctx, async () => {
|
|
6658
|
+
let binding = await this.bindingRegistry.resolve({
|
|
6659
|
+
channel: message.channel,
|
|
6660
|
+
senderId: message.sender.id,
|
|
6661
|
+
channelInstallationId: message.channelInstallationId,
|
|
6662
|
+
tenantId: message.tenantId
|
|
6663
|
+
});
|
|
6664
|
+
if (!binding) {
|
|
6665
|
+
const installation = await this.installationStore.getInstallationById(
|
|
6666
|
+
message.channelInstallationId
|
|
6667
|
+
);
|
|
6668
|
+
if (installation?.rejectWhenNoBinding) {
|
|
6669
|
+
throw new BindingNotFoundError(
|
|
6670
|
+
`No binding for sender "${message.sender.id}" on channel "${message.channel}"`
|
|
6671
|
+
);
|
|
6672
|
+
}
|
|
6673
|
+
if (installation?.fallbackAgentId) {
|
|
6674
|
+
binding = {
|
|
6675
|
+
id: "fallback",
|
|
6676
|
+
channel: message.channel,
|
|
6677
|
+
channelInstallationId: message.channelInstallationId,
|
|
6678
|
+
tenantId: message.tenantId,
|
|
6679
|
+
senderId: message.sender.id,
|
|
6680
|
+
agentId: installation.fallbackAgentId,
|
|
6681
|
+
threadId: void 0,
|
|
6682
|
+
threadMode: "fixed",
|
|
6683
|
+
enabled: true,
|
|
6684
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
6685
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
6686
|
+
};
|
|
6687
|
+
} else {
|
|
6688
|
+
throw new BindingNotFoundError(
|
|
6689
|
+
`No binding for sender "${message.sender.id}" and no fallback configured`
|
|
6690
|
+
);
|
|
6691
|
+
}
|
|
6692
|
+
}
|
|
6693
|
+
ctx.binding = binding;
|
|
6694
|
+
if (!binding.enabled) {
|
|
6695
|
+
throw new BindingNotFoundError(
|
|
6696
|
+
`Binding for sender "${message.sender.id}" is disabled`
|
|
6697
|
+
);
|
|
6698
|
+
}
|
|
6699
|
+
let threadId = ctx.binding.threadId;
|
|
6700
|
+
if (!threadId) {
|
|
6701
|
+
const threadStore = (0, import_core28.getStoreLattice)("default", "thread").store;
|
|
6702
|
+
const newThreadId = (0, import_crypto8.randomUUID)();
|
|
6703
|
+
const newThread = await threadStore.createThread(
|
|
6704
|
+
message.tenantId,
|
|
6705
|
+
ctx.binding.agentId,
|
|
6706
|
+
newThreadId,
|
|
6707
|
+
{
|
|
6708
|
+
metadata: {
|
|
6709
|
+
channel: message.channel,
|
|
6710
|
+
channelInstallationId: message.channelInstallationId,
|
|
6711
|
+
senderId: message.sender.id,
|
|
6712
|
+
bindingId: ctx.binding.id
|
|
6713
|
+
}
|
|
6714
|
+
}
|
|
6715
|
+
);
|
|
6716
|
+
threadId = newThread.id;
|
|
6717
|
+
if (ctx.binding.id !== "fallback") {
|
|
6718
|
+
await this.bindingRegistry.update(ctx.binding.id, { threadId });
|
|
6719
|
+
ctx.binding.threadId = threadId;
|
|
6720
|
+
} else {
|
|
6721
|
+
ctx.binding.threadId = threadId;
|
|
6722
|
+
}
|
|
6723
|
+
}
|
|
6724
|
+
const agent = import_core28.agentInstanceManager.getAgent({
|
|
6725
|
+
tenant_id: message.tenantId,
|
|
6726
|
+
assistant_id: ctx.binding.agentId,
|
|
6727
|
+
thread_id: threadId,
|
|
6728
|
+
workspace_id: ctx.binding.workspaceId || "",
|
|
6729
|
+
project_id: ctx.binding.projectId || ""
|
|
6730
|
+
});
|
|
6731
|
+
const invokeResult = await agent.invoke({
|
|
6732
|
+
input: { message: message.content.text }
|
|
6733
|
+
});
|
|
6734
|
+
ctx.result = extractTextFromInvokeResult(invokeResult);
|
|
6735
|
+
if (message.replyTarget) {
|
|
6736
|
+
const adapter = this.adapterRegistry.get(message.replyTarget.adapterChannel);
|
|
6737
|
+
if (adapter) {
|
|
6738
|
+
const installation = await this.installationStore.getInstallationById(
|
|
6739
|
+
message.channelInstallationId
|
|
6740
|
+
);
|
|
6741
|
+
if (installation) {
|
|
6742
|
+
await adapter.sendReply(
|
|
6743
|
+
message.replyTarget,
|
|
6744
|
+
{ text: ctx.result },
|
|
6745
|
+
installation
|
|
6746
|
+
);
|
|
6747
|
+
}
|
|
6748
|
+
}
|
|
6749
|
+
}
|
|
6750
|
+
});
|
|
6751
|
+
return {
|
|
6752
|
+
success: true,
|
|
6753
|
+
bindingId: ctx.binding?.id,
|
|
6754
|
+
threadId: ctx.binding?.threadId,
|
|
6755
|
+
result: ctx.result
|
|
6756
|
+
};
|
|
6757
|
+
} catch (error) {
|
|
6758
|
+
ctx.error = error instanceof Error ? error : new Error(String(error));
|
|
6759
|
+
return {
|
|
6760
|
+
success: false,
|
|
6761
|
+
bindingId: ctx.binding?.id,
|
|
6762
|
+
threadId: ctx.binding?.threadId,
|
|
6763
|
+
error: ctx.error
|
|
6764
|
+
};
|
|
6765
|
+
}
|
|
6766
|
+
}
|
|
6767
|
+
async runMiddlewares(ctx, finalHandler) {
|
|
6768
|
+
const dispatch = (index) => {
|
|
6769
|
+
if (index >= this.middlewares.length) {
|
|
6770
|
+
return finalHandler();
|
|
6771
|
+
}
|
|
6772
|
+
const middleware = this.middlewares[index];
|
|
6773
|
+
return middleware(ctx, () => dispatch(index + 1));
|
|
6774
|
+
};
|
|
6775
|
+
return dispatch(0);
|
|
6776
|
+
}
|
|
6777
|
+
};
|
|
6778
|
+
function extractTextFromInvokeResult(result) {
|
|
6779
|
+
if (result && typeof result === "object" && "messages" in result) {
|
|
6780
|
+
const messages = result.messages;
|
|
6781
|
+
if (Array.isArray(messages)) {
|
|
6782
|
+
const aiMessages = messages.filter((m) => m.role === "ai");
|
|
6783
|
+
if (aiMessages.length > 0) {
|
|
6784
|
+
return aiMessages.map((m) => m.content).join("\n");
|
|
6785
|
+
}
|
|
6786
|
+
}
|
|
6787
|
+
}
|
|
6788
|
+
return JSON.stringify(result);
|
|
6789
|
+
}
|
|
6790
|
+
|
|
6791
|
+
// src/channels/registry.ts
|
|
6792
|
+
var ChannelAdapterRegistry = class {
|
|
6793
|
+
constructor() {
|
|
6794
|
+
this.adapters = /* @__PURE__ */ new Map();
|
|
6795
|
+
}
|
|
6796
|
+
register(adapter) {
|
|
6797
|
+
if (this.adapters.has(adapter.channel)) {
|
|
6798
|
+
throw new Error(`Channel adapter "${adapter.channel}" already registered`);
|
|
6799
|
+
}
|
|
6800
|
+
this.adapters.set(adapter.channel, adapter);
|
|
6801
|
+
}
|
|
6802
|
+
get(channel) {
|
|
6803
|
+
return this.adapters.get(channel);
|
|
6804
|
+
}
|
|
6805
|
+
list() {
|
|
6806
|
+
return Array.from(this.adapters.keys());
|
|
6807
|
+
}
|
|
6808
|
+
};
|
|
6809
|
+
|
|
6810
|
+
// src/router/middlewares/deduplication.ts
|
|
6811
|
+
var processedMessages = /* @__PURE__ */ new Map();
|
|
6812
|
+
function createDeduplicationMiddleware(ttlMs = 5 * 60 * 1e3) {
|
|
6813
|
+
return async (ctx, next) => {
|
|
6814
|
+
const msg = ctx.inboundMessage;
|
|
6815
|
+
const msgId = msg.content.metadata?.messageId;
|
|
6816
|
+
const key = msgId ? `${msg.channel}:${msg.channelInstallationId}:${msgId}` : `${msg.channel}:${msg.channelInstallationId}:${msg.sender.id}`;
|
|
6817
|
+
const now = Date.now();
|
|
6818
|
+
const lastProcessed = processedMessages.get(key);
|
|
6819
|
+
if (lastProcessed && now - lastProcessed < ttlMs) return;
|
|
6820
|
+
processedMessages.set(key, now);
|
|
6821
|
+
if (processedMessages.size > 1e4) {
|
|
6822
|
+
const oldest = Array.from(processedMessages.entries()).sort((a, b) => a[1] - b[1])[0];
|
|
6823
|
+
if (oldest) processedMessages.delete(oldest[0]);
|
|
6824
|
+
}
|
|
6825
|
+
await next();
|
|
6826
|
+
};
|
|
6827
|
+
}
|
|
6828
|
+
|
|
6829
|
+
// src/router/middlewares/rateLimit.ts
|
|
6830
|
+
var RateLimitError = class extends Error {
|
|
6831
|
+
constructor(message) {
|
|
6832
|
+
super(message);
|
|
6833
|
+
this.name = "RateLimitError";
|
|
6834
|
+
}
|
|
6835
|
+
};
|
|
6836
|
+
var rateCounters = /* @__PURE__ */ new Map();
|
|
6837
|
+
function createRateLimitMiddleware(maxRequests = 10, windowMs = 60 * 1e3, maxEntries = 1e4) {
|
|
6838
|
+
return async (ctx, next) => {
|
|
6839
|
+
const senderKey = `${ctx.inboundMessage.channel}:${ctx.inboundMessage.sender.id}`;
|
|
6840
|
+
const now = Date.now();
|
|
6841
|
+
let counter = rateCounters.get(senderKey);
|
|
6842
|
+
if (!counter || now > counter.resetAt) {
|
|
6843
|
+
counter = { count: 0, resetAt: now + windowMs };
|
|
6844
|
+
}
|
|
6845
|
+
counter.count++;
|
|
6846
|
+
rateCounters.set(senderKey, counter);
|
|
6847
|
+
if (rateCounters.size > maxEntries) {
|
|
6848
|
+
const oldest = Array.from(rateCounters.entries()).sort((a, b) => a[1].resetAt - b[1].resetAt)[0];
|
|
6849
|
+
if (oldest) rateCounters.delete(oldest[0]);
|
|
6850
|
+
}
|
|
6851
|
+
if (counter.count > maxRequests) {
|
|
6852
|
+
throw new RateLimitError(`Rate limit exceeded`);
|
|
6853
|
+
}
|
|
6854
|
+
await next();
|
|
6855
|
+
};
|
|
6856
|
+
}
|
|
6857
|
+
|
|
6858
|
+
// src/router/middlewares/auditLogger.ts
|
|
6859
|
+
var logger2 = new Logger({ serviceName: "lattice/gateway/audit" });
|
|
6860
|
+
function createAuditLoggerMiddleware() {
|
|
6861
|
+
return async (ctx, next) => {
|
|
6862
|
+
const start2 = Date.now();
|
|
6863
|
+
try {
|
|
6864
|
+
await next();
|
|
6865
|
+
logger2.info("message routed", {
|
|
6866
|
+
event: "message:routed",
|
|
6867
|
+
channel: ctx.inboundMessage.channel,
|
|
6868
|
+
senderId: ctx.inboundMessage.sender.id,
|
|
6869
|
+
agentId: ctx.binding?.agentId,
|
|
6870
|
+
threadId: ctx.binding?.threadId,
|
|
6871
|
+
duration: Date.now() - start2,
|
|
6872
|
+
status: "success"
|
|
6873
|
+
});
|
|
6874
|
+
} catch (error) {
|
|
6875
|
+
logger2.error(
|
|
6876
|
+
error instanceof Error ? error.message : String(error),
|
|
6877
|
+
{
|
|
6878
|
+
event: "message:error",
|
|
6879
|
+
channel: ctx.inboundMessage.channel,
|
|
6880
|
+
senderId: ctx.inboundMessage.sender.id,
|
|
6881
|
+
duration: Date.now() - start2,
|
|
6882
|
+
status: "error"
|
|
6883
|
+
}
|
|
6884
|
+
);
|
|
6885
|
+
throw error;
|
|
6886
|
+
}
|
|
6887
|
+
};
|
|
6888
|
+
}
|
|
6889
|
+
|
|
6890
|
+
// src/index.ts
|
|
6891
|
+
var import_core30 = require("@axiom-lattice/core");
|
|
6892
|
+
|
|
6575
6893
|
// src/swagger.ts
|
|
6576
6894
|
var import_swagger = __toESM(require("@fastify/swagger"));
|
|
6577
6895
|
var import_swagger_ui = __toESM(require("@fastify/swagger-ui"));
|
|
@@ -6635,7 +6953,7 @@ var configureSwagger = async (app2, customSwaggerConfig, customSwaggerUiConfig)
|
|
|
6635
6953
|
};
|
|
6636
6954
|
|
|
6637
6955
|
// src/services/agent_task_consumer.ts
|
|
6638
|
-
var
|
|
6956
|
+
var import_core29 = require("@axiom-lattice/core");
|
|
6639
6957
|
var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
6640
6958
|
const {
|
|
6641
6959
|
assistant_id,
|
|
@@ -6653,18 +6971,18 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
6653
6971
|
console.log(
|
|
6654
6972
|
`\u5F00\u59CB\u5904\u7406\u4EFB\u52A1 [assistant_id: ${assistant_id}, thread_id: ${thread_id}]`
|
|
6655
6973
|
);
|
|
6656
|
-
const agent =
|
|
6657
|
-
await agent.addMessage({ input, command, custom_run_config: runConfig },
|
|
6974
|
+
const agent = import_core29.agentInstanceManager.getAgent({ assistant_id, thread_id, tenant_id, workspace_id: runConfig?.workspaceId, project_id: runConfig?.projectId, custom_run_config: runConfig });
|
|
6975
|
+
await agent.addMessage({ input, command, custom_run_config: runConfig }, import_core29.QueueMode.STEER);
|
|
6658
6976
|
if (callback_event) {
|
|
6659
6977
|
agent.subscribeOnce("message:completed", (evt) => {
|
|
6660
|
-
|
|
6978
|
+
import_core29.eventBus.publish(callback_event, {
|
|
6661
6979
|
success: true,
|
|
6662
6980
|
state: evt.state,
|
|
6663
6981
|
config: { assistant_id, thread_id, tenant_id }
|
|
6664
6982
|
});
|
|
6665
6983
|
if (main_thread_id && main_tenant_id) {
|
|
6666
6984
|
try {
|
|
6667
|
-
const mainAgent =
|
|
6985
|
+
const mainAgent = import_core29.agentInstanceManager.getAgent({
|
|
6668
6986
|
assistant_id: main_assistant_id ?? assistant_id,
|
|
6669
6987
|
thread_id: main_thread_id,
|
|
6670
6988
|
tenant_id: main_tenant_id
|
|
@@ -6692,7 +7010,7 @@ ${summary}`
|
|
|
6692
7010
|
}
|
|
6693
7011
|
});
|
|
6694
7012
|
agent.subscribeOnce("message:interrupted", (evt) => {
|
|
6695
|
-
|
|
7013
|
+
import_core29.eventBus.publish(callback_event, {
|
|
6696
7014
|
success: true,
|
|
6697
7015
|
state: evt.state,
|
|
6698
7016
|
config: { assistant_id, thread_id, tenant_id }
|
|
@@ -6716,7 +7034,7 @@ ${summary}`
|
|
|
6716
7034
|
return handleAgentTask(taskRequest, nextRetryCount);
|
|
6717
7035
|
}
|
|
6718
7036
|
if (callback_event) {
|
|
6719
|
-
|
|
7037
|
+
import_core29.eventBus.publish(callback_event, {
|
|
6720
7038
|
success: false,
|
|
6721
7039
|
error: error instanceof Error ? error.message : String(error),
|
|
6722
7040
|
config: { assistant_id, thread_id, tenant_id }
|
|
@@ -6754,7 +7072,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
|
|
|
6754
7072
|
* 初始化事件监听和队列轮询
|
|
6755
7073
|
*/
|
|
6756
7074
|
initialize() {
|
|
6757
|
-
|
|
7075
|
+
import_core29.eventBus.subscribe(import_core29.AGENT_TASK_EVENT, this.trigger_agent_task.bind(this));
|
|
6758
7076
|
this.startPollingQueue();
|
|
6759
7077
|
console.log("Agent\u4EFB\u52A1\u6D88\u8D39\u8005\u5DF2\u542F\u52A8\u5E76\u76D1\u542C\u4EFB\u52A1\u4E8B\u4EF6\u548C\u961F\u5217");
|
|
6760
7078
|
}
|
|
@@ -6873,7 +7191,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
|
|
|
6873
7191
|
handleAgentTask(taskRequest).catch((error) => {
|
|
6874
7192
|
console.error("\u5904\u7406Agent\u4EFB\u52A1\u65F6\u53D1\u751F\u672A\u6355\u83B7\u7684\u9519\u8BEF:", error);
|
|
6875
7193
|
if (taskRequest.callback_event) {
|
|
6876
|
-
|
|
7194
|
+
import_core29.eventBus.publish(taskRequest.callback_event, {
|
|
6877
7195
|
success: false,
|
|
6878
7196
|
error: error instanceof Error ? error.message : String(error),
|
|
6879
7197
|
config: {
|
|
@@ -6894,7 +7212,7 @@ var AgentTaskConsumer = _AgentTaskConsumer;
|
|
|
6894
7212
|
|
|
6895
7213
|
// src/index.ts
|
|
6896
7214
|
var import_core31 = require("@axiom-lattice/core");
|
|
6897
|
-
var
|
|
7215
|
+
var import_protocols4 = require("@axiom-lattice/protocols");
|
|
6898
7216
|
var import_meta = {};
|
|
6899
7217
|
process.on("unhandledRejection", (reason, promise) => {
|
|
6900
7218
|
console.error("\u672A\u5904\u7406\u7684Promise\u62D2\u7EDD:", reason);
|
|
@@ -6902,12 +7220,12 @@ process.on("unhandledRejection", (reason, promise) => {
|
|
|
6902
7220
|
var DEFAULT_LOGGER_CONFIG = {
|
|
6903
7221
|
name: "default",
|
|
6904
7222
|
description: "Default logger for lattice-gateway service",
|
|
6905
|
-
type:
|
|
7223
|
+
type: import_protocols4.LoggerType.PINO,
|
|
6906
7224
|
serviceName: "lattice/gateway",
|
|
6907
7225
|
loggerName: "lattice/gateway"
|
|
6908
7226
|
};
|
|
6909
7227
|
var loggerLattice = initializeLogger(DEFAULT_LOGGER_CONFIG);
|
|
6910
|
-
var
|
|
7228
|
+
var logger3 = loggerLattice.client;
|
|
6911
7229
|
function initializeLogger(config) {
|
|
6912
7230
|
if (import_core31.loggerLatticeManager.hasLattice("default")) {
|
|
6913
7231
|
import_core31.loggerLatticeManager.removeLattice("default");
|
|
@@ -7000,7 +7318,7 @@ app.setErrorHandler((error, request, reply) => {
|
|
|
7000
7318
|
"x-request-id": getHeaderValue(request.headers["x-request-id"]),
|
|
7001
7319
|
"x-user-id": getHeaderValue(request.headers["x-user-id"])
|
|
7002
7320
|
};
|
|
7003
|
-
|
|
7321
|
+
logger3.error(
|
|
7004
7322
|
`\u8BF7\u6C42\u9519\u8BEF: ${request.method} ${request.url} error:${error.message}`,
|
|
7005
7323
|
{
|
|
7006
7324
|
...context,
|
|
@@ -7040,29 +7358,51 @@ var start = async (config) => {
|
|
|
7040
7358
|
file: config.loggerConfig.file || DEFAULT_LOGGER_CONFIG.file
|
|
7041
7359
|
};
|
|
7042
7360
|
loggerLattice = initializeLogger(loggerConfig);
|
|
7043
|
-
|
|
7361
|
+
logger3 = loggerLattice.client;
|
|
7044
7362
|
}
|
|
7045
7363
|
app.decorate("loggerLattice", loggerLattice);
|
|
7046
|
-
|
|
7364
|
+
let channelDeps;
|
|
7365
|
+
try {
|
|
7366
|
+
const { getStoreLattice: getStoreLattice16 } = await import("@axiom-lattice/core");
|
|
7367
|
+
const bindingStore = getStoreLattice16("default", "channelBinding").store;
|
|
7368
|
+
const installationStore = getStoreLattice16("default", "channelInstallation").store;
|
|
7369
|
+
setBindingRegistry(bindingStore);
|
|
7370
|
+
(0, import_core30.setBindingRegistry)(bindingStore);
|
|
7371
|
+
const adapterRegistry = new ChannelAdapterRegistry();
|
|
7372
|
+
adapterRegistry.register(larkChannelAdapter);
|
|
7373
|
+
const router = new MessageRouter({
|
|
7374
|
+
middlewares: [
|
|
7375
|
+
createDeduplicationMiddleware(),
|
|
7376
|
+
createRateLimitMiddleware(),
|
|
7377
|
+
createAuditLoggerMiddleware()
|
|
7378
|
+
],
|
|
7379
|
+
bindingRegistry: bindingStore,
|
|
7380
|
+
adapterRegistry,
|
|
7381
|
+
installationStore
|
|
7382
|
+
});
|
|
7383
|
+
channelDeps = { router, installationStore };
|
|
7384
|
+
} catch {
|
|
7385
|
+
}
|
|
7386
|
+
registerLatticeRoutes(app, channelDeps);
|
|
7047
7387
|
try {
|
|
7048
7388
|
const storeLattice = (0, import_core31.getStoreLattice)("default", "database");
|
|
7049
7389
|
const store = storeLattice.store;
|
|
7050
7390
|
import_core31.sqlDatabaseManager.setConfigStore(store);
|
|
7051
|
-
|
|
7391
|
+
logger3.info("Database config store set for SqlDatabaseManager");
|
|
7052
7392
|
} catch (error) {
|
|
7053
|
-
|
|
7393
|
+
logger3.warn("Failed to set database config store: " + (error instanceof Error ? error.message : String(error)));
|
|
7054
7394
|
}
|
|
7055
7395
|
if (!import_core31.sandboxLatticeManager.hasLattice("default")) {
|
|
7056
7396
|
import_core31.sandboxLatticeManager.registerLattice("default", getConfiguredSandboxProvider());
|
|
7057
|
-
|
|
7397
|
+
logger3.info("Registered sandbox manager from env configuration");
|
|
7058
7398
|
}
|
|
7059
7399
|
const target_port = config?.port || Number(process.env.PORT) || 4001;
|
|
7060
7400
|
await app.listen({ port: target_port, host: "0.0.0.0" });
|
|
7061
|
-
|
|
7401
|
+
logger3.info(`Lattice Gateway is running on port: ${target_port}`);
|
|
7062
7402
|
try {
|
|
7063
|
-
|
|
7403
|
+
logger3.info("AgentLifecycleManager initialized");
|
|
7064
7404
|
} catch (error) {
|
|
7065
|
-
|
|
7405
|
+
logger3.warn("Failed to initialize AgentLifecycleManager", { error });
|
|
7066
7406
|
}
|
|
7067
7407
|
const queueServiceConfig = config?.queueServiceConfig;
|
|
7068
7408
|
if (queueServiceConfig) {
|
|
@@ -7073,14 +7413,14 @@ var start = async (config) => {
|
|
|
7073
7413
|
}
|
|
7074
7414
|
}
|
|
7075
7415
|
try {
|
|
7076
|
-
|
|
7416
|
+
logger3.info("Starting agent instance recovery...");
|
|
7077
7417
|
const restoreStats = await import_core31.agentInstanceManager.restore();
|
|
7078
|
-
|
|
7418
|
+
logger3.info(`Agent recovery complete: ${restoreStats.restored} threads restored, ${restoreStats.errors} errors`);
|
|
7079
7419
|
} catch (error) {
|
|
7080
|
-
|
|
7420
|
+
logger3.error("Agent recovery failed", { error });
|
|
7081
7421
|
}
|
|
7082
7422
|
} catch (err) {
|
|
7083
|
-
|
|
7423
|
+
logger3.error("Server start failed", { error: err });
|
|
7084
7424
|
process.exit(1);
|
|
7085
7425
|
}
|
|
7086
7426
|
};
|