@axiom-lattice/gateway 2.1.97 → 2.1.98
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 +18 -14
- package/CHANGELOG.md +12 -0
- package/dist/WechatChannelAdapter-QQYOHZTL.mjs +249 -0
- package/dist/WechatChannelAdapter-QQYOHZTL.mjs.map +1 -0
- package/dist/chunk-6CUQGDJI.mjs +238 -0
- package/dist/chunk-6CUQGDJI.mjs.map +1 -0
- package/dist/index.js +828 -355
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +121 -145
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
- package/src/channels/lark/LarkChannelAdapter.ts +20 -0
- package/src/channels/routes.ts +2 -0
- package/src/channels/wechat/WechatChannelAdapter.ts +294 -0
- package/src/channels/wechat/context-store.ts +47 -0
- package/src/channels/wechat/controller.ts +59 -0
- package/src/channels/wechat/routes.ts +7 -0
- package/src/channels/wechat/types.ts +62 -0
- package/src/channels/wechat/wechat-client.ts +162 -0
- package/src/controllers/__tests__/run.test.ts +1 -1
- package/src/controllers/__tests__/tasks.test.ts +6 -6
- package/src/controllers/channel-installations.ts +52 -0
- package/src/controllers/database-configs.ts +1 -1
- package/src/controllers/metrics-configs.ts +1 -1
- package/src/controllers/workspace.ts +2 -2
- package/src/index.ts +9 -5
package/dist/index.js
CHANGED
|
@@ -30,6 +30,150 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
30
|
));
|
|
31
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
32
|
|
|
33
|
+
// src/logger/Logger.ts
|
|
34
|
+
var import_pino, import_pino_pretty, import_pino_roll, PinoLoggerFactory, Logger;
|
|
35
|
+
var init_Logger = __esm({
|
|
36
|
+
"src/logger/Logger.ts"() {
|
|
37
|
+
"use strict";
|
|
38
|
+
import_pino = __toESM(require("pino"));
|
|
39
|
+
import_pino_pretty = require("pino-pretty");
|
|
40
|
+
import_pino_roll = require("pino-roll");
|
|
41
|
+
PinoLoggerFactory = class _PinoLoggerFactory {
|
|
42
|
+
constructor() {
|
|
43
|
+
const isProd = process.env.NODE_ENV === "production";
|
|
44
|
+
const loggerConfig = {
|
|
45
|
+
// 自定义时间戳格式
|
|
46
|
+
timestamp: () => `,"@timestamp":"${(/* @__PURE__ */ new Date()).toISOString()}"`,
|
|
47
|
+
// 关闭默认的时间戳键
|
|
48
|
+
base: {
|
|
49
|
+
"@version": "1",
|
|
50
|
+
app_name: "lattice",
|
|
51
|
+
service_name: "lattice/graph-server",
|
|
52
|
+
thread_name: "main",
|
|
53
|
+
logger_name: "lattice-graph-logger"
|
|
54
|
+
},
|
|
55
|
+
formatters: {
|
|
56
|
+
level: (label, number) => {
|
|
57
|
+
return {
|
|
58
|
+
level: label.toUpperCase(),
|
|
59
|
+
level_value: number * 1e3
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
if (isProd) {
|
|
65
|
+
try {
|
|
66
|
+
this.pinoLogger = (0, import_pino.default)(
|
|
67
|
+
loggerConfig,
|
|
68
|
+
import_pino.default.transport({
|
|
69
|
+
target: "pino-roll",
|
|
70
|
+
options: {
|
|
71
|
+
file: "./logs/fin_ai_graph_server",
|
|
72
|
+
frequency: "daily",
|
|
73
|
+
mkdir: true
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error(
|
|
79
|
+
"\u65E0\u6CD5\u521D\u59CB\u5316 pino-roll \u65E5\u5FD7\u8BB0\u5F55\u5668\uFF0C\u56DE\u9000\u5230\u63A7\u5236\u53F0\u65E5\u5FD7",
|
|
80
|
+
error
|
|
81
|
+
);
|
|
82
|
+
this.pinoLogger = (0, import_pino.default)({
|
|
83
|
+
...loggerConfig,
|
|
84
|
+
transport: {
|
|
85
|
+
target: "pino-pretty",
|
|
86
|
+
options: {
|
|
87
|
+
colorize: true
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
this.pinoLogger = (0, import_pino.default)({
|
|
94
|
+
...loggerConfig,
|
|
95
|
+
transport: {
|
|
96
|
+
target: "pino-pretty",
|
|
97
|
+
options: {
|
|
98
|
+
colorize: true
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
static getInstance() {
|
|
105
|
+
if (!_PinoLoggerFactory.instance) {
|
|
106
|
+
_PinoLoggerFactory.instance = new _PinoLoggerFactory();
|
|
107
|
+
}
|
|
108
|
+
return _PinoLoggerFactory.instance;
|
|
109
|
+
}
|
|
110
|
+
getPinoLogger() {
|
|
111
|
+
return this.pinoLogger;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
Logger = class _Logger {
|
|
115
|
+
constructor(options) {
|
|
116
|
+
this.context = options?.context || {};
|
|
117
|
+
this.name = options?.name || "lattice-graph-logger";
|
|
118
|
+
this.serviceName = options?.serviceName || "lattice/graph-server";
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 获取合并了上下文的日志对象
|
|
122
|
+
* @param additionalContext 额外的上下文数据
|
|
123
|
+
* @returns 带有上下文的pino日志对象
|
|
124
|
+
*/
|
|
125
|
+
getContextualLogger(additionalContext) {
|
|
126
|
+
const pinoLogger = PinoLoggerFactory.getInstance().getPinoLogger();
|
|
127
|
+
const contextObj = {
|
|
128
|
+
"x-user-id": this.context["x-user-id"] || "",
|
|
129
|
+
"x-tenant-id": this.context["x-tenant-id"] || "",
|
|
130
|
+
"x-request-id": this.context["x-request-id"] || "",
|
|
131
|
+
"x-task-id": this.context["x-task-id"] || "",
|
|
132
|
+
"x-thread-id": this.context["x-thread-id"] || "",
|
|
133
|
+
service_name: this.serviceName,
|
|
134
|
+
logger_name: this.name,
|
|
135
|
+
...additionalContext
|
|
136
|
+
};
|
|
137
|
+
return pinoLogger.child(contextObj);
|
|
138
|
+
}
|
|
139
|
+
info(msg, obj) {
|
|
140
|
+
this.getContextualLogger(obj).info(msg);
|
|
141
|
+
}
|
|
142
|
+
error(msg, obj) {
|
|
143
|
+
this.getContextualLogger(obj).error(msg);
|
|
144
|
+
}
|
|
145
|
+
warn(msg, obj) {
|
|
146
|
+
this.getContextualLogger(obj).warn(msg);
|
|
147
|
+
}
|
|
148
|
+
debug(msg, obj) {
|
|
149
|
+
this.getContextualLogger(obj).debug(msg);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 更新Logger实例的上下文
|
|
153
|
+
*/
|
|
154
|
+
updateContext(context) {
|
|
155
|
+
this.context = {
|
|
156
|
+
...this.context,
|
|
157
|
+
...context
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* 创建一个新的Logger实例,继承当前Logger的上下文
|
|
162
|
+
*/
|
|
163
|
+
child(options) {
|
|
164
|
+
return new _Logger({
|
|
165
|
+
name: options.name || this.name,
|
|
166
|
+
serviceName: options.serviceName || this.serviceName,
|
|
167
|
+
context: {
|
|
168
|
+
...this.context,
|
|
169
|
+
...options.context
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
33
177
|
// src/channels/lark/sender.ts
|
|
34
178
|
var sender_exports = {};
|
|
35
179
|
__export(sender_exports, {
|
|
@@ -68,6 +212,361 @@ var init_sender = __esm({
|
|
|
68
212
|
}
|
|
69
213
|
});
|
|
70
214
|
|
|
215
|
+
// src/channels/wechat/wechat-client.ts
|
|
216
|
+
function getBaseUrl() {
|
|
217
|
+
return process.env.WECHAT_ILINK_BASE_URL || DEFAULT_BASE_URL;
|
|
218
|
+
}
|
|
219
|
+
function generateWechatUin() {
|
|
220
|
+
const buf = Buffer.alloc(4);
|
|
221
|
+
buf.writeUInt32BE(Math.floor(Math.random() * 4294967295), 0);
|
|
222
|
+
return buf.toString("base64url");
|
|
223
|
+
}
|
|
224
|
+
async function apiGet(path3, extraHeaders) {
|
|
225
|
+
const url = `${getBaseUrl()}${path3}`;
|
|
226
|
+
const headers = { ...extraHeaders };
|
|
227
|
+
const res = await fetch(url, { headers });
|
|
228
|
+
if (!res.ok) {
|
|
229
|
+
throw new Error(`iLink GET ${path3} failed: ${res.status} ${res.statusText}`);
|
|
230
|
+
}
|
|
231
|
+
return res.json();
|
|
232
|
+
}
|
|
233
|
+
async function apiPost(path3, body, botToken, signal) {
|
|
234
|
+
const url = `${getBaseUrl()}${path3}`;
|
|
235
|
+
const headers = {
|
|
236
|
+
"Content-Type": "application/json",
|
|
237
|
+
"AuthorizationType": "ilink_bot_token",
|
|
238
|
+
"X-WECHAT-UIN": generateWechatUin(),
|
|
239
|
+
"Authorization": `Bearer ${botToken}`
|
|
240
|
+
};
|
|
241
|
+
const res = await fetch(url, {
|
|
242
|
+
method: "POST",
|
|
243
|
+
headers,
|
|
244
|
+
body: JSON.stringify(body),
|
|
245
|
+
signal
|
|
246
|
+
});
|
|
247
|
+
if (!res.ok) {
|
|
248
|
+
throw new Error(`iLink POST ${path3} failed: ${res.status} ${res.statusText}`);
|
|
249
|
+
}
|
|
250
|
+
return res.json();
|
|
251
|
+
}
|
|
252
|
+
async function getUpdates(botToken, syncBuffer, signal) {
|
|
253
|
+
const data = await apiPost("/ilink/bot/getupdates", {
|
|
254
|
+
get_updates_buf: syncBuffer,
|
|
255
|
+
base_info: { channel_version: "1.0.2" }
|
|
256
|
+
}, botToken, signal);
|
|
257
|
+
if (data.ret !== void 0 && data.ret !== 0 || data.errcode !== void 0 && data.errcode !== 0) {
|
|
258
|
+
throw new Error(`iLink getUpdates error: ret=${data.ret} errcode=${data.errcode} errmsg=${data.errmsg ?? ""}`);
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
msgs: data.msgs ?? [],
|
|
262
|
+
syncBuffer: data.get_updates_buf ?? syncBuffer
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function generateClientId() {
|
|
266
|
+
return `axiom-wechat:${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
267
|
+
}
|
|
268
|
+
async function sendMessage(botToken, toUserId, text, contextToken) {
|
|
269
|
+
await apiPost("/ilink/bot/sendmessage", {
|
|
270
|
+
msg: {
|
|
271
|
+
from_user_id: "",
|
|
272
|
+
to_user_id: toUserId,
|
|
273
|
+
client_id: generateClientId(),
|
|
274
|
+
message_type: 2,
|
|
275
|
+
// MSG_TYPE_BOT
|
|
276
|
+
message_state: 2,
|
|
277
|
+
// MSG_STATE_FINISH
|
|
278
|
+
item_list: [{ type: 1, text_item: { text } }],
|
|
279
|
+
context_token: contextToken
|
|
280
|
+
},
|
|
281
|
+
base_info: { channel_version: "1.0.2" }
|
|
282
|
+
}, botToken);
|
|
283
|
+
}
|
|
284
|
+
async function getQrCode() {
|
|
285
|
+
const data = await apiGet(
|
|
286
|
+
"/ilink/bot/get_bot_qrcode?bot_type=3"
|
|
287
|
+
);
|
|
288
|
+
if (!data.qrcode || !data.qrcode_img_content) {
|
|
289
|
+
throw new Error("Failed to get WeChat QR code");
|
|
290
|
+
}
|
|
291
|
+
return { qrcode: data.qrcode, qrcodeImgUrl: data.qrcode_img_content };
|
|
292
|
+
}
|
|
293
|
+
async function getQrCodeStatus(qrcode, signal) {
|
|
294
|
+
const data = await apiGet(`/ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`, {
|
|
295
|
+
"iLink-App-ClientVersion": "1"
|
|
296
|
+
});
|
|
297
|
+
return {
|
|
298
|
+
status: data.status || "wait",
|
|
299
|
+
botToken: data.bot_token,
|
|
300
|
+
uin: data.ilink_user_id,
|
|
301
|
+
botId: data.ilink_bot_id,
|
|
302
|
+
baseUrl: data.baseurl
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
var DEFAULT_BASE_URL;
|
|
306
|
+
var init_wechat_client = __esm({
|
|
307
|
+
"src/channels/wechat/wechat-client.ts"() {
|
|
308
|
+
"use strict";
|
|
309
|
+
DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com";
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
// src/channels/wechat/context-store.ts
|
|
314
|
+
function getContextToken(senderId) {
|
|
315
|
+
const entry = store.get(senderId);
|
|
316
|
+
if (!entry) return void 0;
|
|
317
|
+
if (Date.now() - entry.updatedAt > TOKEN_TTL_MS) {
|
|
318
|
+
deleteContextToken(senderId);
|
|
319
|
+
return void 0;
|
|
320
|
+
}
|
|
321
|
+
return entry.token;
|
|
322
|
+
}
|
|
323
|
+
function setContextToken(senderId, token) {
|
|
324
|
+
const existingTimer = timers.get(senderId);
|
|
325
|
+
if (existingTimer) clearTimeout(existingTimer);
|
|
326
|
+
store.set(senderId, { token, senderId, updatedAt: Date.now() });
|
|
327
|
+
const timer = setTimeout(() => {
|
|
328
|
+
store.delete(senderId);
|
|
329
|
+
timers.delete(senderId);
|
|
330
|
+
}, TOKEN_TTL_MS);
|
|
331
|
+
timers.set(senderId, timer);
|
|
332
|
+
}
|
|
333
|
+
function deleteContextToken(senderId) {
|
|
334
|
+
store.delete(senderId);
|
|
335
|
+
const timer = timers.get(senderId);
|
|
336
|
+
if (timer) {
|
|
337
|
+
clearTimeout(timer);
|
|
338
|
+
timers.delete(senderId);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
var TOKEN_TTL_MS, store, timers;
|
|
342
|
+
var init_context_store = __esm({
|
|
343
|
+
"src/channels/wechat/context-store.ts"() {
|
|
344
|
+
"use strict";
|
|
345
|
+
TOKEN_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
346
|
+
store = /* @__PURE__ */ new Map();
|
|
347
|
+
timers = /* @__PURE__ */ new Map();
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// src/channels/wechat/WechatChannelAdapter.ts
|
|
352
|
+
var WechatChannelAdapter_exports = {};
|
|
353
|
+
__export(WechatChannelAdapter_exports, {
|
|
354
|
+
wechatChannelAdapter: () => wechatChannelAdapter
|
|
355
|
+
});
|
|
356
|
+
function addToDedup(clientId) {
|
|
357
|
+
if (!clientId || seenClientIds.has(clientId)) return false;
|
|
358
|
+
seenClientIds.add(clientId);
|
|
359
|
+
if (seenClientIds.size > 1e3) {
|
|
360
|
+
const first = seenClientIds.values().next().value;
|
|
361
|
+
if (first !== void 0) seenClientIds.delete(first);
|
|
362
|
+
}
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
function extractText(msg) {
|
|
366
|
+
if (!msg.item_list?.length) return null;
|
|
367
|
+
for (const item of msg.item_list) {
|
|
368
|
+
if (item.type === MSG_ITEM_TEXT && item.text_item?.text) {
|
|
369
|
+
return item.text_item.text;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
var import_zod2, logger4, wechatConfigSchema, MAX_RECONNECT_DELAY_MS, BASE_RECONNECT_DELAY_MS, HEARTBEAT_INTERVAL_MS, MSG_TYPE_USER, MSG_ITEM_TEXT, activeConnections2, seenClientIds, wechatChannelAdapter;
|
|
375
|
+
var init_WechatChannelAdapter = __esm({
|
|
376
|
+
"src/channels/wechat/WechatChannelAdapter.ts"() {
|
|
377
|
+
"use strict";
|
|
378
|
+
import_zod2 = require("zod");
|
|
379
|
+
init_wechat_client();
|
|
380
|
+
init_context_store();
|
|
381
|
+
init_Logger();
|
|
382
|
+
logger4 = new Logger({ serviceName: "lattice/gateway/wechat" });
|
|
383
|
+
wechatConfigSchema = import_zod2.z.object({
|
|
384
|
+
botToken: import_zod2.z.string(),
|
|
385
|
+
uin: import_zod2.z.string().optional()
|
|
386
|
+
});
|
|
387
|
+
MAX_RECONNECT_DELAY_MS = 3e4;
|
|
388
|
+
BASE_RECONNECT_DELAY_MS = 1e3;
|
|
389
|
+
HEARTBEAT_INTERVAL_MS = 6e4;
|
|
390
|
+
MSG_TYPE_USER = 1;
|
|
391
|
+
MSG_ITEM_TEXT = 1;
|
|
392
|
+
activeConnections2 = /* @__PURE__ */ new Map();
|
|
393
|
+
seenClientIds = /* @__PURE__ */ new Set();
|
|
394
|
+
wechatChannelAdapter = {
|
|
395
|
+
channel: "wechat",
|
|
396
|
+
configSchema: wechatConfigSchema,
|
|
397
|
+
async receive(rawPayload, installation) {
|
|
398
|
+
const msg = rawPayload;
|
|
399
|
+
if (msg.message_type !== MSG_TYPE_USER) return null;
|
|
400
|
+
const senderId = msg.from_user_id;
|
|
401
|
+
if (!senderId) return null;
|
|
402
|
+
const text = extractText(msg);
|
|
403
|
+
if (!text) return null;
|
|
404
|
+
if (msg.context_token) {
|
|
405
|
+
setContextToken(senderId, msg.context_token);
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
channel: "wechat",
|
|
409
|
+
channelInstallationId: installation.id,
|
|
410
|
+
tenantId: installation.tenantId,
|
|
411
|
+
sender: {
|
|
412
|
+
id: senderId,
|
|
413
|
+
displayName: senderId.split("@")[0]
|
|
414
|
+
},
|
|
415
|
+
content: {
|
|
416
|
+
text
|
|
417
|
+
},
|
|
418
|
+
conversation: {
|
|
419
|
+
id: senderId,
|
|
420
|
+
type: "direct"
|
|
421
|
+
},
|
|
422
|
+
replyTarget: {
|
|
423
|
+
adapterChannel: "wechat",
|
|
424
|
+
channelInstallationId: installation.id,
|
|
425
|
+
rawTarget: { senderId }
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
},
|
|
429
|
+
async sendReply(replyTarget, message, installation) {
|
|
430
|
+
const senderId = replyTarget.rawTarget.senderId;
|
|
431
|
+
const contextToken = getContextToken(senderId);
|
|
432
|
+
if (!contextToken) {
|
|
433
|
+
logger4.warn("WeChat context token expired, cannot send reply", {
|
|
434
|
+
installationId: installation.id,
|
|
435
|
+
senderId
|
|
436
|
+
});
|
|
437
|
+
deleteContextToken(senderId);
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const { botToken } = installation.config;
|
|
441
|
+
await sendMessage(botToken, senderId, message.text, contextToken);
|
|
442
|
+
},
|
|
443
|
+
resolveThreadId(message, binding) {
|
|
444
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
445
|
+
const agentId = binding.agentId;
|
|
446
|
+
return `wechat:dm:${message.sender.id}:${agentId}:${date}`;
|
|
447
|
+
},
|
|
448
|
+
async connect(installation, deps) {
|
|
449
|
+
const { id: installationId, tenantId, config } = installation;
|
|
450
|
+
if (!config.botToken) {
|
|
451
|
+
logger4.warn("WeChat installation missing botToken, skipping", { installationId });
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
if (activeConnections2.has(installationId)) {
|
|
455
|
+
logger4.warn("WeChat polling already running for installation, skipping", { installationId });
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
logger4.info("WeChat polling starting", { installationId, tenantId });
|
|
459
|
+
const abortController = new AbortController();
|
|
460
|
+
const heartbeatTimer = setInterval(() => {
|
|
461
|
+
const state2 = activeConnections2.get(installationId);
|
|
462
|
+
if (!state2) {
|
|
463
|
+
clearInterval(heartbeatTimer);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
const elapsed = Date.now() - state2.lastActivity;
|
|
467
|
+
if (elapsed > HEARTBEAT_INTERVAL_MS * 2) {
|
|
468
|
+
logger4.error("WeChat polling heartbeat lost \u2014 no activity", {
|
|
469
|
+
installationId,
|
|
470
|
+
elapsedMs: elapsed
|
|
471
|
+
});
|
|
472
|
+
state2.abortController.abort();
|
|
473
|
+
}
|
|
474
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
475
|
+
const state = {
|
|
476
|
+
installationId,
|
|
477
|
+
abortController,
|
|
478
|
+
lastActivity: Date.now(),
|
|
479
|
+
heartbeatTimer
|
|
480
|
+
};
|
|
481
|
+
activeConnections2.set(installationId, state);
|
|
482
|
+
const router = deps?.router;
|
|
483
|
+
let syncBuffer = "";
|
|
484
|
+
let reconnectDelay = BASE_RECONNECT_DELAY_MS;
|
|
485
|
+
const scheduleNextPoll = () => {
|
|
486
|
+
poll().catch((err) => {
|
|
487
|
+
logger4.error("WeChat poll iteration crashed", {
|
|
488
|
+
installationId,
|
|
489
|
+
error: err instanceof Error ? err.message : String(err)
|
|
490
|
+
});
|
|
491
|
+
const currentState = activeConnections2.get(installationId);
|
|
492
|
+
if (currentState && !currentState.abortController.signal.aborted) {
|
|
493
|
+
setTimeout(scheduleNextPoll, reconnectDelay);
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
};
|
|
497
|
+
const poll = async () => {
|
|
498
|
+
const currentState = activeConnections2.get(installationId);
|
|
499
|
+
if (!currentState || currentState.abortController.signal.aborted) {
|
|
500
|
+
logger4.info("WeChat polling aborted", { installationId });
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
try {
|
|
504
|
+
const result = await getUpdates(
|
|
505
|
+
config.botToken,
|
|
506
|
+
syncBuffer,
|
|
507
|
+
currentState.abortController.signal
|
|
508
|
+
);
|
|
509
|
+
syncBuffer = result.syncBuffer;
|
|
510
|
+
reconnectDelay = BASE_RECONNECT_DELAY_MS;
|
|
511
|
+
currentState.lastActivity = Date.now();
|
|
512
|
+
if (result.msgs.length > 0) {
|
|
513
|
+
logger4.info("WeChat poll received messages", {
|
|
514
|
+
installationId,
|
|
515
|
+
count: result.msgs.length
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
for (const rawMsg of result.msgs) {
|
|
519
|
+
if (rawMsg.message_type !== MSG_TYPE_USER) continue;
|
|
520
|
+
const text = extractText(rawMsg);
|
|
521
|
+
if (!text) continue;
|
|
522
|
+
if (!addToDedup(rawMsg.client_id ?? "")) continue;
|
|
523
|
+
const inbound = await wechatChannelAdapter.receive(
|
|
524
|
+
rawMsg,
|
|
525
|
+
installation
|
|
526
|
+
);
|
|
527
|
+
if (inbound && router) {
|
|
528
|
+
const dispatchResult = await router.dispatch(inbound);
|
|
529
|
+
if (!dispatchResult.success) {
|
|
530
|
+
logger4.warn("WeChat dispatch failed", {
|
|
531
|
+
installationId,
|
|
532
|
+
error: dispatchResult.error?.message
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
} catch (err) {
|
|
538
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
539
|
+
logger4.info("WeChat poll aborted by signal", { installationId });
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
logger4.error("WeChat poll error", {
|
|
543
|
+
installationId,
|
|
544
|
+
error: err instanceof Error ? err.message : String(err)
|
|
545
|
+
});
|
|
546
|
+
await new Promise((resolve) => setTimeout(resolve, reconnectDelay));
|
|
547
|
+
reconnectDelay = Math.min(reconnectDelay * 2, MAX_RECONNECT_DELAY_MS);
|
|
548
|
+
}
|
|
549
|
+
scheduleNextPoll();
|
|
550
|
+
};
|
|
551
|
+
scheduleNextPoll();
|
|
552
|
+
logger4.info("WeChat polling started", { installationId });
|
|
553
|
+
},
|
|
554
|
+
async disconnect(installationId) {
|
|
555
|
+
const state = activeConnections2.get(installationId);
|
|
556
|
+
if (!state) {
|
|
557
|
+
logger4.warn("WeChat polling not running, nothing to disconnect", { installationId });
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
logger4.info("WeChat polling disconnecting", { installationId });
|
|
561
|
+
state.abortController.abort();
|
|
562
|
+
clearInterval(state.heartbeatTimer);
|
|
563
|
+
activeConnections2.delete(installationId);
|
|
564
|
+
logger4.info("WeChat polling disconnected", { installationId });
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
|
|
71
570
|
// src/routes/a2a.ts
|
|
72
571
|
var a2a_exports = {};
|
|
73
572
|
__export(a2a_exports, {
|
|
@@ -75,8 +574,8 @@ __export(a2a_exports, {
|
|
|
75
574
|
registerA2ARoutes: () => registerA2ARoutes,
|
|
76
575
|
setA2AKeyStore: () => setA2AKeyStore
|
|
77
576
|
});
|
|
78
|
-
function setA2AKeyStore(
|
|
79
|
-
_a2aKeyStore =
|
|
577
|
+
function setA2AKeyStore(store2) {
|
|
578
|
+
_a2aKeyStore = store2;
|
|
80
579
|
}
|
|
81
580
|
async function refreshStoreKeyMap() {
|
|
82
581
|
if (!_a2aKeyStore) return;
|
|
@@ -2294,7 +2793,7 @@ async function executeDataQuery(request, reply) {
|
|
|
2294
2793
|
};
|
|
2295
2794
|
}
|
|
2296
2795
|
const storeLattice = (0, import_core12.getStoreLattice)("default", "metrics");
|
|
2297
|
-
const
|
|
2796
|
+
const store2 = storeLattice.store;
|
|
2298
2797
|
if (!body.serverKey) {
|
|
2299
2798
|
reply.code(400);
|
|
2300
2799
|
return {
|
|
@@ -2302,7 +2801,7 @@ async function executeDataQuery(request, reply) {
|
|
|
2302
2801
|
message: "serverKey is required"
|
|
2303
2802
|
};
|
|
2304
2803
|
}
|
|
2305
|
-
const config = await
|
|
2804
|
+
const config = await store2.getConfigByKey(tenantId, body.serverKey);
|
|
2306
2805
|
if (!config) {
|
|
2307
2806
|
reply.code(404);
|
|
2308
2807
|
return {
|
|
@@ -2454,9 +2953,9 @@ async function getAllWorkflowDefinitions(request, reply) {
|
|
|
2454
2953
|
}
|
|
2455
2954
|
const runMap = /* @__PURE__ */ new Map();
|
|
2456
2955
|
try {
|
|
2457
|
-
const
|
|
2458
|
-
if (
|
|
2459
|
-
const runs = await
|
|
2956
|
+
const store2 = getTrackingStore();
|
|
2957
|
+
if (store2) {
|
|
2958
|
+
const runs = await store2.getWorkflowRunsByTenantId(tenantId);
|
|
2460
2959
|
for (const r of runs) {
|
|
2461
2960
|
const entry = runMap.get(r.assistantId) || { runCount: 0 };
|
|
2462
2961
|
entry.runCount++;
|
|
@@ -2490,8 +2989,8 @@ async function getAllWorkflowRuns(request, reply) {
|
|
|
2490
2989
|
const tenantId = getTenantId6(request);
|
|
2491
2990
|
const { assistantId, status } = request.query;
|
|
2492
2991
|
try {
|
|
2493
|
-
const
|
|
2494
|
-
if (!
|
|
2992
|
+
const store2 = getTrackingStore();
|
|
2993
|
+
if (!store2) {
|
|
2495
2994
|
return reply.status(404).send({ success: false, message: "No workflow tracking store configured" });
|
|
2496
2995
|
}
|
|
2497
2996
|
const nameMap = {};
|
|
@@ -2506,9 +3005,9 @@ async function getAllWorkflowRuns(request, reply) {
|
|
|
2506
3005
|
}
|
|
2507
3006
|
let runs;
|
|
2508
3007
|
if (assistantId) {
|
|
2509
|
-
runs = await
|
|
3008
|
+
runs = await store2.getWorkflowRunsByAssistantId(tenantId, assistantId);
|
|
2510
3009
|
} else {
|
|
2511
|
-
runs = await
|
|
3010
|
+
runs = await store2.getWorkflowRunsByTenantId(tenantId);
|
|
2512
3011
|
}
|
|
2513
3012
|
if (status) {
|
|
2514
3013
|
runs = runs.filter((r) => r.status === status);
|
|
@@ -2516,7 +3015,7 @@ async function getAllWorkflowRuns(request, reply) {
|
|
|
2516
3015
|
const enrichedRuns = await Promise.all(
|
|
2517
3016
|
runs.map(async (run) => {
|
|
2518
3017
|
try {
|
|
2519
|
-
const steps = await
|
|
3018
|
+
const steps = await store2.getRunSteps(run.id);
|
|
2520
3019
|
const totalSteps = steps.length;
|
|
2521
3020
|
const completedSteps = steps.filter((s) => s.status === "completed").length;
|
|
2522
3021
|
return { ...run, totalSteps, completedSteps, assistantName: nameMap[run.assistantId] || run.assistantId };
|
|
@@ -2541,8 +3040,8 @@ async function getAllWorkflowRuns(request, reply) {
|
|
|
2541
3040
|
async function getInboxItems(request, reply) {
|
|
2542
3041
|
const tenantId = getTenantId6(request);
|
|
2543
3042
|
try {
|
|
2544
|
-
const
|
|
2545
|
-
if (!
|
|
3043
|
+
const store2 = getTrackingStore();
|
|
3044
|
+
if (!store2) {
|
|
2546
3045
|
return { success: true, message: "No tracking store configured", data: { records: [] } };
|
|
2547
3046
|
}
|
|
2548
3047
|
const nameMap = {};
|
|
@@ -2555,7 +3054,7 @@ async function getInboxItems(request, reply) {
|
|
|
2555
3054
|
}
|
|
2556
3055
|
} catch {
|
|
2557
3056
|
}
|
|
2558
|
-
const runs = await
|
|
3057
|
+
const runs = await store2.getWorkflowRunsByTenantId(tenantId);
|
|
2559
3058
|
const pendingRuns = runs.filter((r) => r.status === "interrupted");
|
|
2560
3059
|
if (pendingRuns.length === 0) {
|
|
2561
3060
|
return { success: true, message: "No pending workflows", data: { records: [] } };
|
|
@@ -2563,7 +3062,7 @@ async function getInboxItems(request, reply) {
|
|
|
2563
3062
|
const checkPromises = pendingRuns.map(async (r) => {
|
|
2564
3063
|
try {
|
|
2565
3064
|
const [steps, agent] = await Promise.all([
|
|
2566
|
-
|
|
3065
|
+
store2.getRunSteps(r.id).catch(() => []),
|
|
2567
3066
|
(async () => {
|
|
2568
3067
|
try {
|
|
2569
3068
|
return import_core13.agentInstanceManager.getAgent({
|
|
@@ -2632,11 +3131,11 @@ async function getWorkflowDefinitions(request, reply) {
|
|
|
2632
3131
|
const { assistantId } = request.params;
|
|
2633
3132
|
const tenantId = getTenantId6(request);
|
|
2634
3133
|
try {
|
|
2635
|
-
const
|
|
2636
|
-
if (!
|
|
3134
|
+
const store2 = getTrackingStore();
|
|
3135
|
+
if (!store2) {
|
|
2637
3136
|
return reply.status(404).send({ success: false, message: "No workflow tracking store configured" });
|
|
2638
3137
|
}
|
|
2639
|
-
const runs = await
|
|
3138
|
+
const runs = await store2.getWorkflowRunsByAssistantId(tenantId, assistantId);
|
|
2640
3139
|
const seen = /* @__PURE__ */ new Set();
|
|
2641
3140
|
const definitions = runs.filter((r) => {
|
|
2642
3141
|
const key = JSON.stringify(r.topologyEdges);
|
|
@@ -2663,11 +3162,11 @@ async function getWorkflowRuns(request, reply) {
|
|
|
2663
3162
|
const { threadId } = request.params;
|
|
2664
3163
|
const tenantId = getTenantId6(request);
|
|
2665
3164
|
try {
|
|
2666
|
-
const
|
|
2667
|
-
if (!
|
|
3165
|
+
const store2 = getTrackingStore();
|
|
3166
|
+
if (!store2) {
|
|
2668
3167
|
return reply.status(404).send({ success: false, message: "No workflow tracking store configured" });
|
|
2669
3168
|
}
|
|
2670
|
-
const runs = await
|
|
3169
|
+
const runs = await store2.getWorkflowRunsByThreadId(tenantId, threadId);
|
|
2671
3170
|
return {
|
|
2672
3171
|
success: true,
|
|
2673
3172
|
message: "Successfully retrieved workflow runs",
|
|
@@ -2681,11 +3180,11 @@ async function getWorkflowRuns(request, reply) {
|
|
|
2681
3180
|
async function getWorkflowRun(request, reply) {
|
|
2682
3181
|
const { runId } = request.params;
|
|
2683
3182
|
try {
|
|
2684
|
-
const
|
|
2685
|
-
if (!
|
|
3183
|
+
const store2 = getTrackingStore();
|
|
3184
|
+
if (!store2) {
|
|
2686
3185
|
return reply.status(404).send({ success: false, message: "No workflow tracking store configured" });
|
|
2687
3186
|
}
|
|
2688
|
-
const run = await
|
|
3187
|
+
const run = await store2.getWorkflowRun(runId);
|
|
2689
3188
|
if (!run) {
|
|
2690
3189
|
return reply.status(404).send({ success: false, message: "Workflow run not found" });
|
|
2691
3190
|
}
|
|
@@ -2699,11 +3198,11 @@ async function deleteWorkflowRun(request, reply) {
|
|
|
2699
3198
|
const { runId } = request.params;
|
|
2700
3199
|
const tenantId = getTenantId6(request);
|
|
2701
3200
|
try {
|
|
2702
|
-
const
|
|
2703
|
-
if (!
|
|
3201
|
+
const store2 = getTrackingStore();
|
|
3202
|
+
if (!store2) {
|
|
2704
3203
|
return reply.status(404).send({ success: false, message: "No workflow tracking store configured" });
|
|
2705
3204
|
}
|
|
2706
|
-
const run = await
|
|
3205
|
+
const run = await store2.getWorkflowRun(runId);
|
|
2707
3206
|
if (!run) {
|
|
2708
3207
|
return reply.status(404).send({ success: false, message: "Workflow run not found" });
|
|
2709
3208
|
}
|
|
@@ -2723,7 +3222,7 @@ async function deleteWorkflowRun(request, reply) {
|
|
|
2723
3222
|
request.log.warn({ runId, error: err.message }, "Failed to abort agent, deleting tracking records anyway");
|
|
2724
3223
|
}
|
|
2725
3224
|
}
|
|
2726
|
-
await
|
|
3225
|
+
await store2.deleteWorkflowRun(runId);
|
|
2727
3226
|
return { success: true, message: "Workflow run deleted" };
|
|
2728
3227
|
} catch (error) {
|
|
2729
3228
|
request.log.error(error, "Failed to delete workflow run");
|
|
@@ -2734,15 +3233,15 @@ async function getRunSteps(request, reply) {
|
|
|
2734
3233
|
const { runId } = request.params;
|
|
2735
3234
|
const { step_type, status: stepStatus } = request.query;
|
|
2736
3235
|
try {
|
|
2737
|
-
const
|
|
2738
|
-
if (!
|
|
3236
|
+
const store2 = getTrackingStore();
|
|
3237
|
+
if (!store2) {
|
|
2739
3238
|
return reply.status(404).send({ success: false, message: "No workflow tracking store configured" });
|
|
2740
3239
|
}
|
|
2741
3240
|
let steps;
|
|
2742
3241
|
if (step_type) {
|
|
2743
|
-
steps = await
|
|
3242
|
+
steps = await store2.getRunStepsByType(runId, step_type);
|
|
2744
3243
|
} else {
|
|
2745
|
-
steps = await
|
|
3244
|
+
steps = await store2.getRunSteps(runId);
|
|
2746
3245
|
}
|
|
2747
3246
|
if (stepStatus) {
|
|
2748
3247
|
steps = steps.filter((s) => s.status === stepStatus);
|
|
@@ -2763,11 +3262,11 @@ async function getRunSteps(request, reply) {
|
|
|
2763
3262
|
async function getRunTasks(request, reply) {
|
|
2764
3263
|
const { runId } = request.params;
|
|
2765
3264
|
try {
|
|
2766
|
-
const
|
|
2767
|
-
if (!
|
|
3265
|
+
const store2 = getTrackingStore();
|
|
3266
|
+
if (!store2) {
|
|
2768
3267
|
return reply.status(404).send({ success: false, message: "No workflow tracking store configured" });
|
|
2769
3268
|
}
|
|
2770
|
-
const steps = await
|
|
3269
|
+
const steps = await store2.getInterruptedSteps(runId);
|
|
2771
3270
|
return {
|
|
2772
3271
|
success: true,
|
|
2773
3272
|
message: "Successfully retrieved user tasks",
|
|
@@ -2782,14 +3281,14 @@ async function replyInboxTask(request, reply) {
|
|
|
2782
3281
|
const { runId, answers } = request.body;
|
|
2783
3282
|
const tenantId = getTenantId6(request);
|
|
2784
3283
|
try {
|
|
2785
|
-
const
|
|
2786
|
-
if (!
|
|
3284
|
+
const store2 = getTrackingStore();
|
|
3285
|
+
if (!store2) {
|
|
2787
3286
|
return reply.status(404).send({
|
|
2788
3287
|
success: false,
|
|
2789
3288
|
message: "No workflow tracking store configured"
|
|
2790
3289
|
});
|
|
2791
3290
|
}
|
|
2792
|
-
const run = await
|
|
3291
|
+
const run = await store2.getWorkflowRun(runId);
|
|
2793
3292
|
if (!run) {
|
|
2794
3293
|
return reply.status(404).send({
|
|
2795
3294
|
success: false,
|
|
@@ -2894,8 +3393,8 @@ async function createPersonalAssistant(request, reply) {
|
|
|
2894
3393
|
if (!name || !personality) {
|
|
2895
3394
|
return reply.status(400).send({ success: false, message: "name and personality are required" });
|
|
2896
3395
|
}
|
|
2897
|
-
const
|
|
2898
|
-
const existing = await
|
|
3396
|
+
const store2 = getAssistantStore();
|
|
3397
|
+
const existing = await store2.getByOwner(tenantId, userId);
|
|
2899
3398
|
if (existing) {
|
|
2900
3399
|
return reply.status(409).send({ success: false, message: "You already have a personal assistant" });
|
|
2901
3400
|
}
|
|
@@ -2911,7 +3410,7 @@ async function createPersonalAssistant(request, reply) {
|
|
|
2911
3410
|
config.key = assistantId;
|
|
2912
3411
|
import_core14.PersonalAssistantConfig.render(config, name, personality);
|
|
2913
3412
|
const data = { name, graphDefinition: config, ownerUserId: userId };
|
|
2914
|
-
const assistant = await
|
|
3413
|
+
const assistant = await store2.createAssistant(tenantId, assistantId, data);
|
|
2915
3414
|
const meta = await getLinkMeta(userId, tenantId);
|
|
2916
3415
|
meta.personalAssistantId = assistantId;
|
|
2917
3416
|
meta.personalProjectId = projectId;
|
|
@@ -2926,8 +3425,8 @@ async function createPersonalAssistant(request, reply) {
|
|
|
2926
3425
|
async function getPersonalAssistant(request, reply) {
|
|
2927
3426
|
const tenantId = getTenantId7(request);
|
|
2928
3427
|
const userId = getUserId3(request);
|
|
2929
|
-
const
|
|
2930
|
-
const assistant = await
|
|
3428
|
+
const store2 = getAssistantStore();
|
|
3429
|
+
const assistant = await store2.getByOwner(tenantId, userId);
|
|
2931
3430
|
if (!assistant) {
|
|
2932
3431
|
return reply.status(404).send({ success: false, message: "No personal assistant found" });
|
|
2933
3432
|
}
|
|
@@ -2943,12 +3442,12 @@ async function getPersonalAssistant(request, reply) {
|
|
|
2943
3442
|
async function deletePersonalAssistant(request, reply) {
|
|
2944
3443
|
const tenantId = getTenantId7(request);
|
|
2945
3444
|
const userId = getUserId3(request);
|
|
2946
|
-
const
|
|
2947
|
-
const assistant = await
|
|
3445
|
+
const store2 = getAssistantStore();
|
|
3446
|
+
const assistant = await store2.getByOwner(tenantId, userId);
|
|
2948
3447
|
if (!assistant) {
|
|
2949
3448
|
return reply.status(404).send({ success: false, message: "No personal assistant found" });
|
|
2950
3449
|
}
|
|
2951
|
-
const deleted = await
|
|
3450
|
+
const deleted = await store2.deleteAssistant(tenantId, assistant.id);
|
|
2952
3451
|
if (!deleted) {
|
|
2953
3452
|
return reply.status(500).send({ success: false, message: "Failed to delete personal assistant" });
|
|
2954
3453
|
}
|
|
@@ -2996,8 +3495,8 @@ async function listTasks(request, reply) {
|
|
|
2996
3495
|
const tenantId = getTenantId8(request);
|
|
2997
3496
|
const userId = getUserId4(request);
|
|
2998
3497
|
const query = request.query;
|
|
2999
|
-
const
|
|
3000
|
-
const tasks = await
|
|
3498
|
+
const store2 = getStore();
|
|
3499
|
+
const tasks = await store2.list({
|
|
3001
3500
|
tenantId,
|
|
3002
3501
|
ownerId: query.ownerId || userId,
|
|
3003
3502
|
status: query.status,
|
|
@@ -3017,8 +3516,8 @@ async function getTask(request, reply) {
|
|
|
3017
3516
|
const tenantId = getTenantId8(request);
|
|
3018
3517
|
const userId = getUserId4(request);
|
|
3019
3518
|
const { id } = request.params;
|
|
3020
|
-
const
|
|
3021
|
-
const task = await
|
|
3519
|
+
const store2 = getStore();
|
|
3520
|
+
const task = await store2.getById(tenantId, id);
|
|
3022
3521
|
if (!task) {
|
|
3023
3522
|
return reply.status(404).send({ success: false, error: "Task not found" });
|
|
3024
3523
|
}
|
|
@@ -3038,8 +3537,8 @@ async function createTask(request, reply) {
|
|
|
3038
3537
|
if (!body.title) {
|
|
3039
3538
|
return reply.status(400).send({ success: false, error: "title is required" });
|
|
3040
3539
|
}
|
|
3041
|
-
const
|
|
3042
|
-
const task = await
|
|
3540
|
+
const store2 = getStore();
|
|
3541
|
+
const task = await store2.create({
|
|
3043
3542
|
...body,
|
|
3044
3543
|
tenantId,
|
|
3045
3544
|
ownerType: body.ownerType || "user",
|
|
@@ -3055,15 +3554,15 @@ async function updateTask(request, reply) {
|
|
|
3055
3554
|
const tenantId = getTenantId8(request);
|
|
3056
3555
|
const userId = getUserId4(request);
|
|
3057
3556
|
const { id } = request.params;
|
|
3058
|
-
const
|
|
3059
|
-
const existing = await
|
|
3557
|
+
const store2 = getStore();
|
|
3558
|
+
const existing = await store2.getById(tenantId, id);
|
|
3060
3559
|
if (!existing) {
|
|
3061
3560
|
return reply.status(404).send({ success: false, error: "Task not found" });
|
|
3062
3561
|
}
|
|
3063
3562
|
if (existing.ownerType === "user" && existing.ownerId !== userId) {
|
|
3064
3563
|
return reply.status(403).send({ success: false, error: "Access denied" });
|
|
3065
3564
|
}
|
|
3066
|
-
const task = await
|
|
3565
|
+
const task = await store2.update(tenantId, id, request.body);
|
|
3067
3566
|
if (!task) {
|
|
3068
3567
|
return reply.status(404).send({ success: false, error: "Task not found" });
|
|
3069
3568
|
}
|
|
@@ -3077,15 +3576,15 @@ async function deleteTask(request, reply) {
|
|
|
3077
3576
|
const tenantId = getTenantId8(request);
|
|
3078
3577
|
const userId = getUserId4(request);
|
|
3079
3578
|
const { id } = request.params;
|
|
3080
|
-
const
|
|
3081
|
-
const existing = await
|
|
3579
|
+
const store2 = getStore();
|
|
3580
|
+
const existing = await store2.getById(tenantId, id);
|
|
3082
3581
|
if (!existing) {
|
|
3083
3582
|
return reply.status(404).send({ success: false, error: "Task not found" });
|
|
3084
3583
|
}
|
|
3085
3584
|
if (existing.ownerType === "user" && existing.ownerId !== userId) {
|
|
3086
3585
|
return reply.status(403).send({ success: false, error: "Access denied" });
|
|
3087
3586
|
}
|
|
3088
|
-
const deleted = await
|
|
3587
|
+
const deleted = await store2.delete(tenantId, id);
|
|
3089
3588
|
if (!deleted) {
|
|
3090
3589
|
return reply.status(404).send({ success: false, error: "Task not found" });
|
|
3091
3590
|
}
|
|
@@ -3099,15 +3598,15 @@ async function completeTask(request, reply) {
|
|
|
3099
3598
|
const tenantId = getTenantId8(request);
|
|
3100
3599
|
const userId = getUserId4(request);
|
|
3101
3600
|
const { id } = request.params;
|
|
3102
|
-
const
|
|
3103
|
-
const existing = await
|
|
3601
|
+
const store2 = getStore();
|
|
3602
|
+
const existing = await store2.getById(tenantId, id);
|
|
3104
3603
|
if (!existing) {
|
|
3105
3604
|
return reply.status(404).send({ success: false, error: "Task not found" });
|
|
3106
3605
|
}
|
|
3107
3606
|
if (existing.ownerType === "user" && existing.ownerId !== userId) {
|
|
3108
3607
|
return reply.status(403).send({ success: false, error: "Access denied" });
|
|
3109
3608
|
}
|
|
3110
|
-
const task = await
|
|
3609
|
+
const task = await store2.update(tenantId, id, { status: "completed" });
|
|
3111
3610
|
if (!task) {
|
|
3112
3611
|
return reply.status(404).send({ success: false, error: "Task not found" });
|
|
3113
3612
|
}
|
|
@@ -4125,7 +4624,7 @@ var WorkspaceController = class {
|
|
|
4125
4624
|
}
|
|
4126
4625
|
const inferredContentType = this.getMimeType(filename2);
|
|
4127
4626
|
try {
|
|
4128
|
-
|
|
4627
|
+
const contentType = inferredContentType;
|
|
4129
4628
|
const isHtml = contentType?.toLowerCase().includes("text/html") || filename2.toLowerCase().endsWith(".html") || filename2.toLowerCase().endsWith(".htm");
|
|
4130
4629
|
let outputBuf = buf;
|
|
4131
4630
|
if (isHtml) {
|
|
@@ -4237,7 +4736,7 @@ var WorkspaceController = class {
|
|
|
4237
4736
|
const filename = data.filename || "file";
|
|
4238
4737
|
const pathEntry = data.fields?.path;
|
|
4239
4738
|
const pathValue = pathEntry && typeof pathEntry === "object" && "value" in pathEntry ? String(pathEntry.value) : typeof pathEntry === "string" ? pathEntry : void 0;
|
|
4240
|
-
if (pathValue && !/^[a-zA-Z0-9_
|
|
4739
|
+
if (pathValue && !/^[a-zA-Z0-9_./~-]+$/.test(pathValue)) {
|
|
4241
4740
|
return reply.status(400).send({ success: false, error: "Invalid path parameter" });
|
|
4242
4741
|
}
|
|
4243
4742
|
if (workspace.storageType === "sandbox") {
|
|
@@ -4362,8 +4861,8 @@ async function getDatabaseConfigList(request, reply) {
|
|
|
4362
4861
|
const tenantId = getTenantId9(request);
|
|
4363
4862
|
try {
|
|
4364
4863
|
const storeLattice = (0, import_core22.getStoreLattice)("default", "database");
|
|
4365
|
-
const
|
|
4366
|
-
const configs = await
|
|
4864
|
+
const store2 = storeLattice.store;
|
|
4865
|
+
const configs = await store2.getAllConfigs(tenantId);
|
|
4367
4866
|
console.log("Backend: getAllConfigs returned:", configs);
|
|
4368
4867
|
if (configs.length > 0) {
|
|
4369
4868
|
console.log("Backend: First config key:", configs[0].key);
|
|
@@ -4393,8 +4892,8 @@ async function getDatabaseConfig(request, reply) {
|
|
|
4393
4892
|
const { key } = request.params;
|
|
4394
4893
|
try {
|
|
4395
4894
|
const storeLattice = (0, import_core22.getStoreLattice)("default", "database");
|
|
4396
|
-
const
|
|
4397
|
-
const config = await
|
|
4895
|
+
const store2 = storeLattice.store;
|
|
4896
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
4398
4897
|
if (!config) {
|
|
4399
4898
|
return {
|
|
4400
4899
|
success: false,
|
|
@@ -4419,8 +4918,8 @@ async function createDatabaseConfig(request, reply) {
|
|
|
4419
4918
|
const body = request.body;
|
|
4420
4919
|
try {
|
|
4421
4920
|
const storeLattice = (0, import_core22.getStoreLattice)("default", "database");
|
|
4422
|
-
const
|
|
4423
|
-
const existing = await
|
|
4921
|
+
const store2 = storeLattice.store;
|
|
4922
|
+
const existing = await store2.getConfigByKey(tenantId, body.key);
|
|
4424
4923
|
if (existing) {
|
|
4425
4924
|
reply.code(409);
|
|
4426
4925
|
return {
|
|
@@ -4429,7 +4928,7 @@ async function createDatabaseConfig(request, reply) {
|
|
|
4429
4928
|
};
|
|
4430
4929
|
}
|
|
4431
4930
|
const id = body.id || (0, import_crypto4.randomUUID)();
|
|
4432
|
-
const config = await
|
|
4931
|
+
const config = await store2.createConfig(tenantId, id, body);
|
|
4433
4932
|
try {
|
|
4434
4933
|
import_core22.sqlDatabaseManager.registerDatabase(tenantId, config.key, config.config);
|
|
4435
4934
|
} catch (error) {
|
|
@@ -4455,8 +4954,8 @@ async function updateDatabaseConfig(request, reply) {
|
|
|
4455
4954
|
const updates = request.body;
|
|
4456
4955
|
try {
|
|
4457
4956
|
const storeLattice = (0, import_core22.getStoreLattice)("default", "database");
|
|
4458
|
-
const
|
|
4459
|
-
const existing = await
|
|
4957
|
+
const store2 = storeLattice.store;
|
|
4958
|
+
const existing = await store2.getConfigByKey(tenantId, key);
|
|
4460
4959
|
if (!existing) {
|
|
4461
4960
|
reply.code(404);
|
|
4462
4961
|
return {
|
|
@@ -4464,7 +4963,7 @@ async function updateDatabaseConfig(request, reply) {
|
|
|
4464
4963
|
message: "Database configuration not found"
|
|
4465
4964
|
};
|
|
4466
4965
|
}
|
|
4467
|
-
const updated = await
|
|
4966
|
+
const updated = await store2.updateConfig(tenantId, existing.id, updates);
|
|
4468
4967
|
if (!updated) {
|
|
4469
4968
|
return {
|
|
4470
4969
|
success: false,
|
|
@@ -4496,12 +4995,12 @@ async function deleteDatabaseConfig(request, reply) {
|
|
|
4496
4995
|
const { keyOrId } = request.params;
|
|
4497
4996
|
try {
|
|
4498
4997
|
const storeLattice = (0, import_core22.getStoreLattice)("default", "database");
|
|
4499
|
-
const
|
|
4998
|
+
const store2 = storeLattice.store;
|
|
4500
4999
|
console.log("Delete request - keyOrId:", keyOrId);
|
|
4501
|
-
let config = await
|
|
5000
|
+
let config = await store2.getConfigByKey(tenantId, keyOrId);
|
|
4502
5001
|
let configKey = keyOrId;
|
|
4503
5002
|
if (!config) {
|
|
4504
|
-
config = await
|
|
5003
|
+
config = await store2.getConfigById(tenantId, keyOrId);
|
|
4505
5004
|
if (config) {
|
|
4506
5005
|
configKey = config.key;
|
|
4507
5006
|
}
|
|
@@ -4514,7 +5013,7 @@ async function deleteDatabaseConfig(request, reply) {
|
|
|
4514
5013
|
};
|
|
4515
5014
|
}
|
|
4516
5015
|
console.log("Found config to delete:", { id: config.id, key: config.key });
|
|
4517
|
-
const deleted = await
|
|
5016
|
+
const deleted = await store2.deleteConfig(tenantId, config.id);
|
|
4518
5017
|
if (!deleted) {
|
|
4519
5018
|
return {
|
|
4520
5019
|
success: false,
|
|
@@ -4545,8 +5044,8 @@ async function testDatabaseConnection(request, reply) {
|
|
|
4545
5044
|
const { key } = request.params;
|
|
4546
5045
|
try {
|
|
4547
5046
|
const storeLattice = (0, import_core22.getStoreLattice)("default", "database");
|
|
4548
|
-
const
|
|
4549
|
-
const config = await
|
|
5047
|
+
const store2 = storeLattice.store;
|
|
5048
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
4550
5049
|
if (!config) {
|
|
4551
5050
|
reply.code(404);
|
|
4552
5051
|
return {
|
|
@@ -4641,8 +5140,8 @@ async function getMetricsServerConfigList(request, reply) {
|
|
|
4641
5140
|
const tenantId = getTenantId10(request);
|
|
4642
5141
|
try {
|
|
4643
5142
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
4644
|
-
const
|
|
4645
|
-
const configs = await
|
|
5143
|
+
const store2 = storeLattice.store;
|
|
5144
|
+
const configs = await store2.getAllConfigs(tenantId);
|
|
4646
5145
|
return {
|
|
4647
5146
|
success: true,
|
|
4648
5147
|
message: "Metrics server configurations retrieved successfully",
|
|
@@ -4668,8 +5167,8 @@ async function getMetricsServerConfig(request, reply) {
|
|
|
4668
5167
|
const { key } = request.params;
|
|
4669
5168
|
try {
|
|
4670
5169
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
4671
|
-
const
|
|
4672
|
-
const config = await
|
|
5170
|
+
const store2 = storeLattice.store;
|
|
5171
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
4673
5172
|
if (!config) {
|
|
4674
5173
|
return {
|
|
4675
5174
|
success: false,
|
|
@@ -4694,8 +5193,8 @@ async function createMetricsServerConfig(request, reply) {
|
|
|
4694
5193
|
const body = request.body;
|
|
4695
5194
|
try {
|
|
4696
5195
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
4697
|
-
const
|
|
4698
|
-
const existing = await
|
|
5196
|
+
const store2 = storeLattice.store;
|
|
5197
|
+
const existing = await store2.getConfigByKey(tenantId, body.key);
|
|
4699
5198
|
if (existing) {
|
|
4700
5199
|
reply.code(409);
|
|
4701
5200
|
return {
|
|
@@ -4720,7 +5219,7 @@ async function createMetricsServerConfig(request, reply) {
|
|
|
4720
5219
|
selectedDataSources: body.selectedDataSources || []
|
|
4721
5220
|
} : body.config
|
|
4722
5221
|
};
|
|
4723
|
-
const config = await
|
|
5222
|
+
const config = await store2.createConfig(tenantId, id, configData);
|
|
4724
5223
|
try {
|
|
4725
5224
|
import_core23.metricsServerManager.registerServer(tenantId, config.key, config.config);
|
|
4726
5225
|
} catch (error) {
|
|
@@ -4746,8 +5245,8 @@ async function updateMetricsServerConfig(request, reply) {
|
|
|
4746
5245
|
const updates = request.body;
|
|
4747
5246
|
try {
|
|
4748
5247
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
4749
|
-
const
|
|
4750
|
-
const existing = await
|
|
5248
|
+
const store2 = storeLattice.store;
|
|
5249
|
+
const existing = await store2.getConfigByKey(tenantId, key);
|
|
4751
5250
|
if (!existing) {
|
|
4752
5251
|
reply.code(404);
|
|
4753
5252
|
return {
|
|
@@ -4764,7 +5263,7 @@ async function updateMetricsServerConfig(request, reply) {
|
|
|
4764
5263
|
selectedDataSources: updates.selectedDataSources
|
|
4765
5264
|
};
|
|
4766
5265
|
}
|
|
4767
|
-
const updated = await
|
|
5266
|
+
const updated = await store2.updateConfig(tenantId, existing.id, updates);
|
|
4768
5267
|
if (!updated) {
|
|
4769
5268
|
return {
|
|
4770
5269
|
success: false,
|
|
@@ -4796,11 +5295,11 @@ async function deleteMetricsServerConfig(request, reply) {
|
|
|
4796
5295
|
const { keyOrId } = request.params;
|
|
4797
5296
|
try {
|
|
4798
5297
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
4799
|
-
const
|
|
4800
|
-
let config = await
|
|
5298
|
+
const store2 = storeLattice.store;
|
|
5299
|
+
let config = await store2.getConfigByKey(tenantId, keyOrId);
|
|
4801
5300
|
let configKey = keyOrId;
|
|
4802
5301
|
if (!config) {
|
|
4803
|
-
config = await
|
|
5302
|
+
config = await store2.getConfigById(tenantId, keyOrId);
|
|
4804
5303
|
if (config) {
|
|
4805
5304
|
configKey = config.key;
|
|
4806
5305
|
}
|
|
@@ -4812,7 +5311,7 @@ async function deleteMetricsServerConfig(request, reply) {
|
|
|
4812
5311
|
message: "Metrics server configuration not found"
|
|
4813
5312
|
};
|
|
4814
5313
|
}
|
|
4815
|
-
const deleted = await
|
|
5314
|
+
const deleted = await store2.deleteConfig(tenantId, config.id);
|
|
4816
5315
|
if (!deleted) {
|
|
4817
5316
|
return {
|
|
4818
5317
|
success: false,
|
|
@@ -4843,8 +5342,8 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
4843
5342
|
const { key } = request.params;
|
|
4844
5343
|
try {
|
|
4845
5344
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
4846
|
-
const
|
|
4847
|
-
const config = await
|
|
5345
|
+
const store2 = storeLattice.store;
|
|
5346
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
4848
5347
|
if (!config) {
|
|
4849
5348
|
reply.code(404);
|
|
4850
5349
|
return {
|
|
@@ -4894,8 +5393,8 @@ async function listAvailableMetrics(request, reply) {
|
|
|
4894
5393
|
const { key } = request.params;
|
|
4895
5394
|
try {
|
|
4896
5395
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
4897
|
-
const
|
|
4898
|
-
const config = await
|
|
5396
|
+
const store2 = storeLattice.store;
|
|
5397
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
4899
5398
|
if (!config) {
|
|
4900
5399
|
reply.code(404);
|
|
4901
5400
|
return {
|
|
@@ -4933,8 +5432,8 @@ async function queryMetricsData(request, reply) {
|
|
|
4933
5432
|
const { metricName, startTime, endTime, step, labels } = request.body;
|
|
4934
5433
|
try {
|
|
4935
5434
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
4936
|
-
const
|
|
4937
|
-
const config = await
|
|
5435
|
+
const store2 = storeLattice.store;
|
|
5436
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
4938
5437
|
if (!config) {
|
|
4939
5438
|
reply.code(404);
|
|
4940
5439
|
return {
|
|
@@ -4980,8 +5479,8 @@ async function getDataSources(request, reply) {
|
|
|
4980
5479
|
const { key } = request.params;
|
|
4981
5480
|
try {
|
|
4982
5481
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
4983
|
-
const
|
|
4984
|
-
const config = await
|
|
5482
|
+
const store2 = storeLattice.store;
|
|
5483
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
4985
5484
|
if (!config) {
|
|
4986
5485
|
reply.code(404);
|
|
4987
5486
|
return {
|
|
@@ -5021,8 +5520,8 @@ async function getDatasourceMetrics(request, reply) {
|
|
|
5021
5520
|
const { key, datasourceId } = request.params;
|
|
5022
5521
|
try {
|
|
5023
5522
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
5024
|
-
const
|
|
5025
|
-
const config = await
|
|
5523
|
+
const store2 = storeLattice.store;
|
|
5524
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
5026
5525
|
if (!config) {
|
|
5027
5526
|
reply.code(404);
|
|
5028
5527
|
return {
|
|
@@ -5059,8 +5558,8 @@ async function querySemanticMetrics(request, reply) {
|
|
|
5059
5558
|
const body = request.body;
|
|
5060
5559
|
try {
|
|
5061
5560
|
const storeLattice = (0, import_core23.getStoreLattice)("default", "metrics");
|
|
5062
|
-
const
|
|
5063
|
-
const config = await
|
|
5561
|
+
const store2 = storeLattice.store;
|
|
5562
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
5064
5563
|
if (!config) {
|
|
5065
5564
|
reply.code(404);
|
|
5066
5565
|
return {
|
|
@@ -5224,8 +5723,8 @@ async function getMcpServerConfigList(request, reply) {
|
|
|
5224
5723
|
const tenantId = getTenantId11(request);
|
|
5225
5724
|
try {
|
|
5226
5725
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5227
|
-
const
|
|
5228
|
-
const configs = await
|
|
5726
|
+
const store2 = storeLattice.store;
|
|
5727
|
+
const configs = await store2.getAllConfigs(tenantId);
|
|
5229
5728
|
return {
|
|
5230
5729
|
success: true,
|
|
5231
5730
|
message: "MCP server configurations retrieved successfully",
|
|
@@ -5251,8 +5750,8 @@ async function getMcpServerConfig(request, reply) {
|
|
|
5251
5750
|
const { key } = request.params;
|
|
5252
5751
|
try {
|
|
5253
5752
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5254
|
-
const
|
|
5255
|
-
const config = await
|
|
5753
|
+
const store2 = storeLattice.store;
|
|
5754
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
5256
5755
|
if (!config) {
|
|
5257
5756
|
return {
|
|
5258
5757
|
success: false,
|
|
@@ -5277,8 +5776,8 @@ async function createMcpServerConfig(request, reply) {
|
|
|
5277
5776
|
const body = request.body;
|
|
5278
5777
|
try {
|
|
5279
5778
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5280
|
-
const
|
|
5281
|
-
const existing = await
|
|
5779
|
+
const store2 = storeLattice.store;
|
|
5780
|
+
const existing = await store2.getConfigByKey(tenantId, body.key);
|
|
5282
5781
|
if (existing) {
|
|
5283
5782
|
reply.code(409);
|
|
5284
5783
|
return {
|
|
@@ -5287,14 +5786,14 @@ async function createMcpServerConfig(request, reply) {
|
|
|
5287
5786
|
};
|
|
5288
5787
|
}
|
|
5289
5788
|
const id = body.id || (0, import_crypto6.randomUUID)();
|
|
5290
|
-
const config = await
|
|
5789
|
+
const config = await store2.createConfig(tenantId, id, body);
|
|
5291
5790
|
try {
|
|
5292
5791
|
await connectAndRegisterTools(config);
|
|
5293
|
-
await
|
|
5792
|
+
await store2.updateConfig(tenantId, id, { status: "connected" });
|
|
5294
5793
|
config.status = "connected";
|
|
5295
5794
|
} catch (error) {
|
|
5296
5795
|
console.warn("Failed to auto-connect MCP server:", error);
|
|
5297
|
-
await
|
|
5796
|
+
await store2.updateConfig(tenantId, id, { status: "error" });
|
|
5298
5797
|
config.status = "error";
|
|
5299
5798
|
}
|
|
5300
5799
|
reply.code(201);
|
|
@@ -5317,8 +5816,8 @@ async function updateMcpServerConfig(request, reply) {
|
|
|
5317
5816
|
const updates = request.body;
|
|
5318
5817
|
try {
|
|
5319
5818
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5320
|
-
const
|
|
5321
|
-
const existing = await
|
|
5819
|
+
const store2 = storeLattice.store;
|
|
5820
|
+
const existing = await store2.getConfigByKey(tenantId, key);
|
|
5322
5821
|
if (!existing) {
|
|
5323
5822
|
reply.code(404);
|
|
5324
5823
|
return {
|
|
@@ -5327,7 +5826,7 @@ async function updateMcpServerConfig(request, reply) {
|
|
|
5327
5826
|
};
|
|
5328
5827
|
}
|
|
5329
5828
|
const shouldReconnect = updates.config !== void 0;
|
|
5330
|
-
const updated = await
|
|
5829
|
+
const updated = await store2.updateConfig(tenantId, existing.id, updates);
|
|
5331
5830
|
if (!updated) {
|
|
5332
5831
|
return {
|
|
5333
5832
|
success: false,
|
|
@@ -5340,11 +5839,11 @@ async function updateMcpServerConfig(request, reply) {
|
|
|
5340
5839
|
await import_core24.mcpManager.removeServer(key);
|
|
5341
5840
|
}
|
|
5342
5841
|
await connectAndRegisterTools(updated);
|
|
5343
|
-
await
|
|
5842
|
+
await store2.updateConfig(tenantId, existing.id, { status: "connected" });
|
|
5344
5843
|
updated.status = "connected";
|
|
5345
5844
|
} catch (error) {
|
|
5346
5845
|
console.warn("Failed to reconnect MCP server:", error);
|
|
5347
|
-
await
|
|
5846
|
+
await store2.updateConfig(tenantId, existing.id, { status: "error" });
|
|
5348
5847
|
updated.status = "error";
|
|
5349
5848
|
}
|
|
5350
5849
|
}
|
|
@@ -5366,11 +5865,11 @@ async function deleteMcpServerConfig(request, reply) {
|
|
|
5366
5865
|
const { keyOrId } = request.params;
|
|
5367
5866
|
try {
|
|
5368
5867
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5369
|
-
const
|
|
5370
|
-
let config = await
|
|
5868
|
+
const store2 = storeLattice.store;
|
|
5869
|
+
let config = await store2.getConfigByKey(tenantId, keyOrId);
|
|
5371
5870
|
let configKey = keyOrId;
|
|
5372
5871
|
if (!config) {
|
|
5373
|
-
config = await
|
|
5872
|
+
config = await store2.getConfigById(tenantId, keyOrId);
|
|
5374
5873
|
if (config) {
|
|
5375
5874
|
configKey = config.key;
|
|
5376
5875
|
}
|
|
@@ -5389,7 +5888,7 @@ async function deleteMcpServerConfig(request, reply) {
|
|
|
5389
5888
|
} catch (error) {
|
|
5390
5889
|
console.warn("Failed to remove from MCP manager:", error);
|
|
5391
5890
|
}
|
|
5392
|
-
const deleted = await
|
|
5891
|
+
const deleted = await store2.deleteConfig(tenantId, config.id);
|
|
5393
5892
|
if (!deleted) {
|
|
5394
5893
|
return {
|
|
5395
5894
|
success: false,
|
|
@@ -5413,8 +5912,8 @@ async function testMcpServerConnection(request, reply) {
|
|
|
5413
5912
|
const { key } = request.params;
|
|
5414
5913
|
try {
|
|
5415
5914
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5416
|
-
const
|
|
5417
|
-
const config = await
|
|
5915
|
+
const store2 = storeLattice.store;
|
|
5916
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
5418
5917
|
if (!config) {
|
|
5419
5918
|
reply.code(404);
|
|
5420
5919
|
return {
|
|
@@ -5466,8 +5965,8 @@ async function listMcpServerTools(request, reply) {
|
|
|
5466
5965
|
const { key } = request.params;
|
|
5467
5966
|
try {
|
|
5468
5967
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5469
|
-
const
|
|
5470
|
-
const config = await
|
|
5968
|
+
const store2 = storeLattice.store;
|
|
5969
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
5471
5970
|
if (!config) {
|
|
5472
5971
|
reply.code(404);
|
|
5473
5972
|
return {
|
|
@@ -5499,8 +5998,8 @@ async function connectMcpServer(request, reply) {
|
|
|
5499
5998
|
const { key } = request.params;
|
|
5500
5999
|
try {
|
|
5501
6000
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5502
|
-
const
|
|
5503
|
-
const config = await
|
|
6001
|
+
const store2 = storeLattice.store;
|
|
6002
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
5504
6003
|
if (!config) {
|
|
5505
6004
|
reply.code(404);
|
|
5506
6005
|
return {
|
|
@@ -5509,7 +6008,7 @@ async function connectMcpServer(request, reply) {
|
|
|
5509
6008
|
};
|
|
5510
6009
|
}
|
|
5511
6010
|
await connectAndRegisterTools(config);
|
|
5512
|
-
const updated = await
|
|
6011
|
+
const updated = await store2.updateConfig(tenantId, config.id, {
|
|
5513
6012
|
status: "connected"
|
|
5514
6013
|
});
|
|
5515
6014
|
return {
|
|
@@ -5520,10 +6019,10 @@ async function connectMcpServer(request, reply) {
|
|
|
5520
6019
|
} catch (error) {
|
|
5521
6020
|
console.error("Failed to connect MCP server:", error);
|
|
5522
6021
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5523
|
-
const
|
|
5524
|
-
const config = await
|
|
6022
|
+
const store2 = storeLattice.store;
|
|
6023
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
5525
6024
|
if (config) {
|
|
5526
|
-
await
|
|
6025
|
+
await store2.updateConfig(tenantId, config.id, { status: "error" });
|
|
5527
6026
|
}
|
|
5528
6027
|
return {
|
|
5529
6028
|
success: false,
|
|
@@ -5536,8 +6035,8 @@ async function disconnectMcpServer(request, reply) {
|
|
|
5536
6035
|
const { key } = request.params;
|
|
5537
6036
|
try {
|
|
5538
6037
|
const storeLattice = (0, import_core24.getStoreLattice)("default", "mcp");
|
|
5539
|
-
const
|
|
5540
|
-
const config = await
|
|
6038
|
+
const store2 = storeLattice.store;
|
|
6039
|
+
const config = await store2.getConfigByKey(tenantId, key);
|
|
5541
6040
|
if (!config) {
|
|
5542
6041
|
reply.code(404);
|
|
5543
6042
|
return {
|
|
@@ -5548,7 +6047,7 @@ async function disconnectMcpServer(request, reply) {
|
|
|
5548
6047
|
if (import_core24.mcpManager.hasServer(key)) {
|
|
5549
6048
|
await import_core24.mcpManager.removeServer(key);
|
|
5550
6049
|
}
|
|
5551
|
-
const updated = await
|
|
6050
|
+
const updated = await store2.updateConfig(tenantId, config.id, {
|
|
5552
6051
|
status: "disconnected"
|
|
5553
6052
|
});
|
|
5554
6053
|
return {
|
|
@@ -5665,18 +6164,18 @@ var EvalRunner = class {
|
|
|
5665
6164
|
return this.eventEmitter;
|
|
5666
6165
|
}
|
|
5667
6166
|
async startRun(tenantId, projectId) {
|
|
5668
|
-
const
|
|
5669
|
-
const project = await
|
|
6167
|
+
const store2 = this.getEvalStore();
|
|
6168
|
+
const project = await store2.getProjectById(tenantId, projectId);
|
|
5670
6169
|
if (!project) throw new Error("Project not found");
|
|
5671
|
-
const existingRuns = await
|
|
6170
|
+
const existingRuns = await store2.getRunsByTenant(tenantId, { projectId, status: "running" });
|
|
5672
6171
|
if (existingRuns.length > 0) {
|
|
5673
6172
|
throw new Error("A run is already in progress for this project");
|
|
5674
6173
|
}
|
|
5675
|
-
const suites = await
|
|
6174
|
+
const suites = await store2.getSuitesByProject(tenantId, projectId);
|
|
5676
6175
|
const evalSuites = [];
|
|
5677
6176
|
let totalCases = 0;
|
|
5678
6177
|
for (const suite of suites) {
|
|
5679
|
-
const cases = await
|
|
6178
|
+
const cases = await store2.getCasesBySuite(tenantId, suite.id);
|
|
5680
6179
|
totalCases += cases.length;
|
|
5681
6180
|
evalSuites.push({
|
|
5682
6181
|
suiteName: suite.name,
|
|
@@ -5698,7 +6197,7 @@ var EvalRunner = class {
|
|
|
5698
6197
|
}
|
|
5699
6198
|
const runId = (0, import_uuid3.v4)();
|
|
5700
6199
|
const concurrency = project.concurrency || 3;
|
|
5701
|
-
await
|
|
6200
|
+
await store2.createRun(tenantId, projectId, runId, { totalCases, concurrency });
|
|
5702
6201
|
const judgeCfg = project.judgeModelConfig;
|
|
5703
6202
|
const hasModelKey = Boolean(judgeCfg.modelKey);
|
|
5704
6203
|
const hasApiKey = Boolean(judgeCfg.apiKeyEnvName || judgeCfg.apiKey);
|
|
@@ -5738,7 +6237,7 @@ var EvalRunner = class {
|
|
|
5738
6237
|
else stats.failed++;
|
|
5739
6238
|
stats.totalScore += score;
|
|
5740
6239
|
const completedCount = stats.passed + stats.failed;
|
|
5741
|
-
await
|
|
6240
|
+
await store2.createRunResult(tenantId, runId, (0, import_uuid3.v4)(), {
|
|
5742
6241
|
suiteName,
|
|
5743
6242
|
caseId: result.caseId,
|
|
5744
6243
|
pass: passed,
|
|
@@ -5755,7 +6254,7 @@ var EvalRunner = class {
|
|
|
5755
6254
|
error: result.error
|
|
5756
6255
|
});
|
|
5757
6256
|
const avgScore = completedCount > 0 ? stats.totalScore / completedCount : 0;
|
|
5758
|
-
await
|
|
6257
|
+
await store2.updateRunStatus(tenantId, runId, {
|
|
5759
6258
|
passedCases: stats.passed,
|
|
5760
6259
|
failedCases: stats.failed,
|
|
5761
6260
|
avgScore
|
|
@@ -5771,7 +6270,7 @@ var EvalRunner = class {
|
|
|
5771
6270
|
const evalProject = new import_agent_eval.LatticeEvalProject(projectConfig, onCaseComplete);
|
|
5772
6271
|
const { report } = await evalProject.runAllSuitesBatch(concurrency);
|
|
5773
6272
|
const completedCount = stats.passed + stats.failed;
|
|
5774
|
-
await
|
|
6273
|
+
await store2.updateRunStatus(tenantId, runId, {
|
|
5775
6274
|
status: "completed",
|
|
5776
6275
|
completedAt: /* @__PURE__ */ new Date(),
|
|
5777
6276
|
passedCases: stats.passed,
|
|
@@ -5786,7 +6285,7 @@ var EvalRunner = class {
|
|
|
5786
6285
|
return { report };
|
|
5787
6286
|
} catch (err) {
|
|
5788
6287
|
const errorMsg = err.message;
|
|
5789
|
-
await
|
|
6288
|
+
await store2.updateRunStatus(tenantId, runId, {
|
|
5790
6289
|
status: "failed",
|
|
5791
6290
|
error: errorMsg,
|
|
5792
6291
|
completedAt: /* @__PURE__ */ new Date()
|
|
@@ -5810,8 +6309,8 @@ var EvalRunner = class {
|
|
|
5810
6309
|
const ctx = this.runs.get(runId);
|
|
5811
6310
|
if (!ctx) return false;
|
|
5812
6311
|
ctx.abortController.abort();
|
|
5813
|
-
const
|
|
5814
|
-
await
|
|
6312
|
+
const store2 = this.getEvalStore();
|
|
6313
|
+
await store2.updateRunStatus(ctx.tenantId, runId, { status: "aborted", completedAt: /* @__PURE__ */ new Date() });
|
|
5815
6314
|
return true;
|
|
5816
6315
|
}
|
|
5817
6316
|
isRunning(runId) {
|
|
@@ -5837,10 +6336,10 @@ function getEvalStore() {
|
|
|
5837
6336
|
async function createProject(request, reply) {
|
|
5838
6337
|
try {
|
|
5839
6338
|
const tenantId = getTenantId12(request);
|
|
5840
|
-
const
|
|
6339
|
+
const store2 = getEvalStore();
|
|
5841
6340
|
const id = (0, import_uuid4.v4)();
|
|
5842
6341
|
const data = request.body;
|
|
5843
|
-
const project = await
|
|
6342
|
+
const project = await store2.createProject(tenantId, id, {
|
|
5844
6343
|
name: data.name,
|
|
5845
6344
|
description: data.description,
|
|
5846
6345
|
version: data.version,
|
|
@@ -5862,8 +6361,8 @@ async function createProject(request, reply) {
|
|
|
5862
6361
|
async function listProjects(request, reply) {
|
|
5863
6362
|
try {
|
|
5864
6363
|
const tenantId = getTenantId12(request);
|
|
5865
|
-
const
|
|
5866
|
-
let projects = await
|
|
6364
|
+
const store2 = getEvalStore();
|
|
6365
|
+
let projects = await store2.getProjectsByTenant(tenantId);
|
|
5867
6366
|
if (projects.length === 0) {
|
|
5868
6367
|
try {
|
|
5869
6368
|
const { modelLatticeManager: modelLatticeManager3 } = await import("@axiom-lattice/core");
|
|
@@ -5872,14 +6371,14 @@ async function listProjects(request, reply) {
|
|
|
5872
6371
|
const judgeModel = first ? { modelKey: first.key } : { provider: "openai", model: "gpt-4" };
|
|
5873
6372
|
const host = request.hostname || "localhost";
|
|
5874
6373
|
const baseUrl = `http://${host}:${process.env.PORT || 4001}`;
|
|
5875
|
-
await
|
|
6374
|
+
await store2.createProject(tenantId, (0, import_uuid4.v4)(), {
|
|
5876
6375
|
name: "Default",
|
|
5877
6376
|
description: "Built-in project for testing eval against this server",
|
|
5878
6377
|
judgeModelConfig: judgeModel,
|
|
5879
6378
|
targetServerConfig: { base_url: baseUrl, api_key: "" },
|
|
5880
6379
|
concurrency: 3
|
|
5881
6380
|
});
|
|
5882
|
-
projects = await
|
|
6381
|
+
projects = await store2.getProjectsByTenant(tenantId);
|
|
5883
6382
|
} catch {
|
|
5884
6383
|
}
|
|
5885
6384
|
}
|
|
@@ -5896,13 +6395,13 @@ async function listProjects(request, reply) {
|
|
|
5896
6395
|
async function getProject(request, reply) {
|
|
5897
6396
|
try {
|
|
5898
6397
|
const tenantId = getTenantId12(request);
|
|
5899
|
-
const
|
|
6398
|
+
const store2 = getEvalStore();
|
|
5900
6399
|
const { pid } = request.params;
|
|
5901
|
-
const project = await
|
|
6400
|
+
const project = await store2.getProjectById(tenantId, pid);
|
|
5902
6401
|
if (!project) {
|
|
5903
6402
|
return reply.status(404).send({ success: false, message: "Project not found" });
|
|
5904
6403
|
}
|
|
5905
|
-
const suites = await
|
|
6404
|
+
const suites = await store2.getSuitesByProject(tenantId, pid);
|
|
5906
6405
|
return {
|
|
5907
6406
|
success: true,
|
|
5908
6407
|
message: "Ok",
|
|
@@ -5916,13 +6415,13 @@ async function getProject(request, reply) {
|
|
|
5916
6415
|
async function updateProject(request, reply) {
|
|
5917
6416
|
try {
|
|
5918
6417
|
const tenantId = getTenantId12(request);
|
|
5919
|
-
const
|
|
6418
|
+
const store2 = getEvalStore();
|
|
5920
6419
|
const { pid } = request.params;
|
|
5921
|
-
const existing = await
|
|
6420
|
+
const existing = await store2.getProjectById(tenantId, pid);
|
|
5922
6421
|
if (!existing) {
|
|
5923
6422
|
return reply.status(404).send({ success: false, message: "Project not found" });
|
|
5924
6423
|
}
|
|
5925
|
-
const updated = await
|
|
6424
|
+
const updated = await store2.updateProject(tenantId, pid, request.body);
|
|
5926
6425
|
return {
|
|
5927
6426
|
success: true,
|
|
5928
6427
|
message: "Successfully updated project",
|
|
@@ -5936,13 +6435,13 @@ async function updateProject(request, reply) {
|
|
|
5936
6435
|
async function deleteProject(request, reply) {
|
|
5937
6436
|
try {
|
|
5938
6437
|
const tenantId = getTenantId12(request);
|
|
5939
|
-
const
|
|
6438
|
+
const store2 = getEvalStore();
|
|
5940
6439
|
const { pid } = request.params;
|
|
5941
|
-
const existing = await
|
|
6440
|
+
const existing = await store2.getProjectById(tenantId, pid);
|
|
5942
6441
|
if (!existing) {
|
|
5943
6442
|
return reply.status(404).send({ success: false, message: "Project not found" });
|
|
5944
6443
|
}
|
|
5945
|
-
const deleted = await
|
|
6444
|
+
const deleted = await store2.deleteProject(tenantId, pid);
|
|
5946
6445
|
if (!deleted) {
|
|
5947
6446
|
return reply.status(500).send({ success: false, message: "Failed to delete project" });
|
|
5948
6447
|
}
|
|
@@ -5955,15 +6454,15 @@ async function deleteProject(request, reply) {
|
|
|
5955
6454
|
async function createSuite(request, reply) {
|
|
5956
6455
|
try {
|
|
5957
6456
|
const tenantId = getTenantId12(request);
|
|
5958
|
-
const
|
|
6457
|
+
const store2 = getEvalStore();
|
|
5959
6458
|
const { pid } = request.params;
|
|
5960
|
-
const project = await
|
|
6459
|
+
const project = await store2.getProjectById(tenantId, pid);
|
|
5961
6460
|
if (!project) {
|
|
5962
6461
|
return reply.status(404).send({ success: false, message: "Project not found" });
|
|
5963
6462
|
}
|
|
5964
6463
|
const id = (0, import_uuid4.v4)();
|
|
5965
6464
|
const data = request.body;
|
|
5966
|
-
const suite = await
|
|
6465
|
+
const suite = await store2.createSuite(tenantId, pid, id, { name: data.name });
|
|
5967
6466
|
return reply.status(201).send({
|
|
5968
6467
|
success: true,
|
|
5969
6468
|
message: "Successfully created suite",
|
|
@@ -5977,13 +6476,13 @@ async function createSuite(request, reply) {
|
|
|
5977
6476
|
async function updateSuite(request, reply) {
|
|
5978
6477
|
try {
|
|
5979
6478
|
const tenantId = getTenantId12(request);
|
|
5980
|
-
const
|
|
6479
|
+
const store2 = getEvalStore();
|
|
5981
6480
|
const { sid } = request.params;
|
|
5982
|
-
const existing = await
|
|
6481
|
+
const existing = await store2.getSuiteById(tenantId, sid);
|
|
5983
6482
|
if (!existing) {
|
|
5984
6483
|
return reply.status(404).send({ success: false, message: "Suite not found" });
|
|
5985
6484
|
}
|
|
5986
|
-
const updated = await
|
|
6485
|
+
const updated = await store2.updateSuite(tenantId, sid, request.body);
|
|
5987
6486
|
return {
|
|
5988
6487
|
success: true,
|
|
5989
6488
|
message: "Successfully updated suite",
|
|
@@ -5997,13 +6496,13 @@ async function updateSuite(request, reply) {
|
|
|
5997
6496
|
async function deleteSuite(request, reply) {
|
|
5998
6497
|
try {
|
|
5999
6498
|
const tenantId = getTenantId12(request);
|
|
6000
|
-
const
|
|
6499
|
+
const store2 = getEvalStore();
|
|
6001
6500
|
const { sid } = request.params;
|
|
6002
|
-
const existing = await
|
|
6501
|
+
const existing = await store2.getSuiteById(tenantId, sid);
|
|
6003
6502
|
if (!existing) {
|
|
6004
6503
|
return reply.status(404).send({ success: false, message: "Suite not found" });
|
|
6005
6504
|
}
|
|
6006
|
-
const deleted = await
|
|
6505
|
+
const deleted = await store2.deleteSuite(tenantId, sid);
|
|
6007
6506
|
if (!deleted) {
|
|
6008
6507
|
return reply.status(500).send({ success: false, message: "Failed to delete suite" });
|
|
6009
6508
|
}
|
|
@@ -6016,15 +6515,15 @@ async function deleteSuite(request, reply) {
|
|
|
6016
6515
|
async function createCase(request, reply) {
|
|
6017
6516
|
try {
|
|
6018
6517
|
const tenantId = getTenantId12(request);
|
|
6019
|
-
const
|
|
6518
|
+
const store2 = getEvalStore();
|
|
6020
6519
|
const { sid } = request.params;
|
|
6021
|
-
const suite = await
|
|
6520
|
+
const suite = await store2.getSuiteById(tenantId, sid);
|
|
6022
6521
|
if (!suite) {
|
|
6023
6522
|
return reply.status(404).send({ success: false, message: "Suite not found" });
|
|
6024
6523
|
}
|
|
6025
6524
|
const id = (0, import_uuid4.v4)();
|
|
6026
6525
|
const data = request.body;
|
|
6027
|
-
const created = await
|
|
6526
|
+
const created = await store2.createCase(tenantId, sid, id, {
|
|
6028
6527
|
inputMessage: data.inputMessage,
|
|
6029
6528
|
inputFiles: data.inputFiles,
|
|
6030
6529
|
steps: data.steps ?? [],
|
|
@@ -6045,9 +6544,9 @@ async function createCase(request, reply) {
|
|
|
6045
6544
|
async function listCasesForSuite(request, reply) {
|
|
6046
6545
|
try {
|
|
6047
6546
|
const tenantId = getTenantId12(request);
|
|
6048
|
-
const
|
|
6547
|
+
const store2 = getEvalStore();
|
|
6049
6548
|
const { sid } = request.params;
|
|
6050
|
-
const cases = await
|
|
6549
|
+
const cases = await store2.getCasesBySuite(tenantId, sid);
|
|
6051
6550
|
return {
|
|
6052
6551
|
success: true,
|
|
6053
6552
|
message: "Ok",
|
|
@@ -6061,13 +6560,13 @@ async function listCasesForSuite(request, reply) {
|
|
|
6061
6560
|
async function updateCase(request, reply) {
|
|
6062
6561
|
try {
|
|
6063
6562
|
const tenantId = getTenantId12(request);
|
|
6064
|
-
const
|
|
6563
|
+
const store2 = getEvalStore();
|
|
6065
6564
|
const { cid } = request.params;
|
|
6066
|
-
const existing = await
|
|
6565
|
+
const existing = await store2.getCaseById(tenantId, cid);
|
|
6067
6566
|
if (!existing) {
|
|
6068
6567
|
return reply.status(404).send({ success: false, message: "Case not found" });
|
|
6069
6568
|
}
|
|
6070
|
-
const updated = await
|
|
6569
|
+
const updated = await store2.updateCase(tenantId, cid, request.body);
|
|
6071
6570
|
return {
|
|
6072
6571
|
success: true,
|
|
6073
6572
|
message: "Successfully updated case",
|
|
@@ -6081,13 +6580,13 @@ async function updateCase(request, reply) {
|
|
|
6081
6580
|
async function deleteCase(request, reply) {
|
|
6082
6581
|
try {
|
|
6083
6582
|
const tenantId = getTenantId12(request);
|
|
6084
|
-
const
|
|
6583
|
+
const store2 = getEvalStore();
|
|
6085
6584
|
const { cid } = request.params;
|
|
6086
|
-
const existing = await
|
|
6585
|
+
const existing = await store2.getCaseById(tenantId, cid);
|
|
6087
6586
|
if (!existing) {
|
|
6088
6587
|
return reply.status(404).send({ success: false, message: "Case not found" });
|
|
6089
6588
|
}
|
|
6090
|
-
const deleted = await
|
|
6589
|
+
const deleted = await store2.deleteCase(tenantId, cid);
|
|
6091
6590
|
if (!deleted) {
|
|
6092
6591
|
return reply.status(500).send({ success: false, message: "Failed to delete case" });
|
|
6093
6592
|
}
|
|
@@ -6794,145 +7293,8 @@ function normalizeChatType(chatType) {
|
|
|
6794
7293
|
return chatType === "p2p" ? "direct" : "group";
|
|
6795
7294
|
}
|
|
6796
7295
|
|
|
6797
|
-
// src/logger/Logger.ts
|
|
6798
|
-
var import_pino = __toESM(require("pino"));
|
|
6799
|
-
var import_pino_pretty = require("pino-pretty");
|
|
6800
|
-
var import_pino_roll = require("pino-roll");
|
|
6801
|
-
var PinoLoggerFactory = class _PinoLoggerFactory {
|
|
6802
|
-
constructor() {
|
|
6803
|
-
const isProd = process.env.NODE_ENV === "production";
|
|
6804
|
-
const loggerConfig = {
|
|
6805
|
-
// 自定义时间戳格式
|
|
6806
|
-
timestamp: () => `,"@timestamp":"${(/* @__PURE__ */ new Date()).toISOString()}"`,
|
|
6807
|
-
// 关闭默认的时间戳键
|
|
6808
|
-
base: {
|
|
6809
|
-
"@version": "1",
|
|
6810
|
-
app_name: "lattice",
|
|
6811
|
-
service_name: "lattice/graph-server",
|
|
6812
|
-
thread_name: "main",
|
|
6813
|
-
logger_name: "lattice-graph-logger"
|
|
6814
|
-
},
|
|
6815
|
-
formatters: {
|
|
6816
|
-
level: (label, number) => {
|
|
6817
|
-
return {
|
|
6818
|
-
level: label.toUpperCase(),
|
|
6819
|
-
level_value: number * 1e3
|
|
6820
|
-
};
|
|
6821
|
-
}
|
|
6822
|
-
}
|
|
6823
|
-
};
|
|
6824
|
-
if (isProd) {
|
|
6825
|
-
try {
|
|
6826
|
-
this.pinoLogger = (0, import_pino.default)(
|
|
6827
|
-
loggerConfig,
|
|
6828
|
-
import_pino.default.transport({
|
|
6829
|
-
target: "pino-roll",
|
|
6830
|
-
options: {
|
|
6831
|
-
file: "./logs/fin_ai_graph_server",
|
|
6832
|
-
frequency: "daily",
|
|
6833
|
-
mkdir: true
|
|
6834
|
-
}
|
|
6835
|
-
})
|
|
6836
|
-
);
|
|
6837
|
-
} catch (error) {
|
|
6838
|
-
console.error(
|
|
6839
|
-
"\u65E0\u6CD5\u521D\u59CB\u5316 pino-roll \u65E5\u5FD7\u8BB0\u5F55\u5668\uFF0C\u56DE\u9000\u5230\u63A7\u5236\u53F0\u65E5\u5FD7",
|
|
6840
|
-
error
|
|
6841
|
-
);
|
|
6842
|
-
this.pinoLogger = (0, import_pino.default)({
|
|
6843
|
-
...loggerConfig,
|
|
6844
|
-
transport: {
|
|
6845
|
-
target: "pino-pretty",
|
|
6846
|
-
options: {
|
|
6847
|
-
colorize: true
|
|
6848
|
-
}
|
|
6849
|
-
}
|
|
6850
|
-
});
|
|
6851
|
-
}
|
|
6852
|
-
} else {
|
|
6853
|
-
this.pinoLogger = (0, import_pino.default)({
|
|
6854
|
-
...loggerConfig,
|
|
6855
|
-
transport: {
|
|
6856
|
-
target: "pino-pretty",
|
|
6857
|
-
options: {
|
|
6858
|
-
colorize: true
|
|
6859
|
-
}
|
|
6860
|
-
}
|
|
6861
|
-
});
|
|
6862
|
-
}
|
|
6863
|
-
}
|
|
6864
|
-
static getInstance() {
|
|
6865
|
-
if (!_PinoLoggerFactory.instance) {
|
|
6866
|
-
_PinoLoggerFactory.instance = new _PinoLoggerFactory();
|
|
6867
|
-
}
|
|
6868
|
-
return _PinoLoggerFactory.instance;
|
|
6869
|
-
}
|
|
6870
|
-
getPinoLogger() {
|
|
6871
|
-
return this.pinoLogger;
|
|
6872
|
-
}
|
|
6873
|
-
};
|
|
6874
|
-
var Logger = class _Logger {
|
|
6875
|
-
constructor(options) {
|
|
6876
|
-
this.context = options?.context || {};
|
|
6877
|
-
this.name = options?.name || "lattice-graph-logger";
|
|
6878
|
-
this.serviceName = options?.serviceName || "lattice/graph-server";
|
|
6879
|
-
}
|
|
6880
|
-
/**
|
|
6881
|
-
* 获取合并了上下文的日志对象
|
|
6882
|
-
* @param additionalContext 额外的上下文数据
|
|
6883
|
-
* @returns 带有上下文的pino日志对象
|
|
6884
|
-
*/
|
|
6885
|
-
getContextualLogger(additionalContext) {
|
|
6886
|
-
const pinoLogger = PinoLoggerFactory.getInstance().getPinoLogger();
|
|
6887
|
-
const contextObj = {
|
|
6888
|
-
"x-user-id": this.context["x-user-id"] || "",
|
|
6889
|
-
"x-tenant-id": this.context["x-tenant-id"] || "",
|
|
6890
|
-
"x-request-id": this.context["x-request-id"] || "",
|
|
6891
|
-
"x-task-id": this.context["x-task-id"] || "",
|
|
6892
|
-
"x-thread-id": this.context["x-thread-id"] || "",
|
|
6893
|
-
service_name: this.serviceName,
|
|
6894
|
-
logger_name: this.name,
|
|
6895
|
-
...additionalContext
|
|
6896
|
-
};
|
|
6897
|
-
return pinoLogger.child(contextObj);
|
|
6898
|
-
}
|
|
6899
|
-
info(msg, obj) {
|
|
6900
|
-
this.getContextualLogger(obj).info(msg);
|
|
6901
|
-
}
|
|
6902
|
-
error(msg, obj) {
|
|
6903
|
-
this.getContextualLogger(obj).error(msg);
|
|
6904
|
-
}
|
|
6905
|
-
warn(msg, obj) {
|
|
6906
|
-
this.getContextualLogger(obj).warn(msg);
|
|
6907
|
-
}
|
|
6908
|
-
debug(msg, obj) {
|
|
6909
|
-
this.getContextualLogger(obj).debug(msg);
|
|
6910
|
-
}
|
|
6911
|
-
/**
|
|
6912
|
-
* 更新Logger实例的上下文
|
|
6913
|
-
*/
|
|
6914
|
-
updateContext(context) {
|
|
6915
|
-
this.context = {
|
|
6916
|
-
...this.context,
|
|
6917
|
-
...context
|
|
6918
|
-
};
|
|
6919
|
-
}
|
|
6920
|
-
/**
|
|
6921
|
-
* 创建一个新的Logger实例,继承当前Logger的上下文
|
|
6922
|
-
*/
|
|
6923
|
-
child(options) {
|
|
6924
|
-
return new _Logger({
|
|
6925
|
-
name: options.name || this.name,
|
|
6926
|
-
serviceName: options.serviceName || this.serviceName,
|
|
6927
|
-
context: {
|
|
6928
|
-
...this.context,
|
|
6929
|
-
...options.context
|
|
6930
|
-
}
|
|
6931
|
-
});
|
|
6932
|
-
}
|
|
6933
|
-
};
|
|
6934
|
-
|
|
6935
7296
|
// src/channels/lark/LarkChannelAdapter.ts
|
|
7297
|
+
init_Logger();
|
|
6936
7298
|
var Lark = __toESM(require("@larksuiteoapi/node-sdk"));
|
|
6937
7299
|
var logger = new Logger({ serviceName: "lattice/gateway/lark" });
|
|
6938
7300
|
var activeConnections = /* @__PURE__ */ new Map();
|
|
@@ -7064,6 +7426,24 @@ var larkChannelAdapter = {
|
|
|
7064
7426
|
await client.start({ eventDispatcher });
|
|
7065
7427
|
activeConnections.set(installationId, client);
|
|
7066
7428
|
logger.info("Lark WS client connected", { installationId });
|
|
7429
|
+
},
|
|
7430
|
+
async disconnect(installationId) {
|
|
7431
|
+
const client = activeConnections.get(installationId);
|
|
7432
|
+
if (!client) {
|
|
7433
|
+
logger.warn("Lark WS not connected, nothing to disconnect", { installationId });
|
|
7434
|
+
return;
|
|
7435
|
+
}
|
|
7436
|
+
logger.info("Lark WS client disconnecting", { installationId });
|
|
7437
|
+
try {
|
|
7438
|
+
client.close({ force: true });
|
|
7439
|
+
} catch (err) {
|
|
7440
|
+
logger.error("Lark WS client stop error", {
|
|
7441
|
+
installationId,
|
|
7442
|
+
error: err instanceof Error ? err.message : String(err)
|
|
7443
|
+
});
|
|
7444
|
+
}
|
|
7445
|
+
activeConnections.delete(installationId);
|
|
7446
|
+
logger.info("Lark WS client disconnected", { installationId });
|
|
7067
7447
|
}
|
|
7068
7448
|
};
|
|
7069
7449
|
|
|
@@ -7090,6 +7470,7 @@ function decryptLarkPayload(encryptKey, encryptedPayload) {
|
|
|
7090
7470
|
}
|
|
7091
7471
|
|
|
7092
7472
|
// src/channels/lark/controller.ts
|
|
7473
|
+
init_Logger();
|
|
7093
7474
|
var logger2 = new Logger({ serviceName: "lattice/gateway/lark" });
|
|
7094
7475
|
function createLarkEventHandler(deps) {
|
|
7095
7476
|
return async function handleLarkEvent(request, reply) {
|
|
@@ -7131,9 +7512,63 @@ function registerLarkChannelRoutes(app2, deps) {
|
|
|
7131
7512
|
);
|
|
7132
7513
|
}
|
|
7133
7514
|
|
|
7515
|
+
// src/channels/wechat/controller.ts
|
|
7516
|
+
init_wechat_client();
|
|
7517
|
+
var qrSessions = /* @__PURE__ */ new Map();
|
|
7518
|
+
var SESSION_TTL_MS = 5 * 60 * 1e3;
|
|
7519
|
+
function cleanupExpiredSessions() {
|
|
7520
|
+
const now = Date.now();
|
|
7521
|
+
for (const [key, session] of qrSessions) {
|
|
7522
|
+
if (now - session.createdAt > SESSION_TTL_MS) {
|
|
7523
|
+
qrSessions.delete(key);
|
|
7524
|
+
}
|
|
7525
|
+
}
|
|
7526
|
+
}
|
|
7527
|
+
async function handleGetQrCode(_request, reply) {
|
|
7528
|
+
try {
|
|
7529
|
+
cleanupExpiredSessions();
|
|
7530
|
+
const { qrcode, qrcodeImgUrl } = await getQrCode();
|
|
7531
|
+
qrSessions.set(qrcode, { qrcode, createdAt: Date.now() });
|
|
7532
|
+
reply.send({ success: true, data: { qrcode, qrcodeImgUrl } });
|
|
7533
|
+
} catch (err) {
|
|
7534
|
+
reply.status(500).send({
|
|
7535
|
+
success: false,
|
|
7536
|
+
message: err instanceof Error ? err.message : "Failed to get QR code"
|
|
7537
|
+
});
|
|
7538
|
+
}
|
|
7539
|
+
}
|
|
7540
|
+
async function handleGetQrCodeStatus(request, reply) {
|
|
7541
|
+
const { qrcode } = request.query;
|
|
7542
|
+
if (!qrcode) {
|
|
7543
|
+
reply.status(400).send({ success: false, message: "qrcode is required" });
|
|
7544
|
+
return;
|
|
7545
|
+
}
|
|
7546
|
+
const session = qrSessions.get(qrcode);
|
|
7547
|
+
if (!session) {
|
|
7548
|
+
reply.status(404).send({ success: false, message: "Session not found or expired" });
|
|
7549
|
+
return;
|
|
7550
|
+
}
|
|
7551
|
+
try {
|
|
7552
|
+
const result = await getQrCodeStatus(qrcode);
|
|
7553
|
+
reply.send({ success: true, data: result });
|
|
7554
|
+
} catch (err) {
|
|
7555
|
+
reply.status(500).send({
|
|
7556
|
+
success: false,
|
|
7557
|
+
message: err instanceof Error ? err.message : "Failed to check QR status"
|
|
7558
|
+
});
|
|
7559
|
+
}
|
|
7560
|
+
}
|
|
7561
|
+
|
|
7562
|
+
// src/channels/wechat/routes.ts
|
|
7563
|
+
function registerWechatChannelRoutes(app2) {
|
|
7564
|
+
app2.get("/api/channels/wechat/setup/qrcode", handleGetQrCode);
|
|
7565
|
+
app2.get("/api/channels/wechat/setup/status", handleGetQrCodeStatus);
|
|
7566
|
+
}
|
|
7567
|
+
|
|
7134
7568
|
// src/channels/routes.ts
|
|
7135
7569
|
var channelRouteRegistrars = [
|
|
7136
|
-
(app2, deps) => registerLarkChannelRoutes(app2, deps)
|
|
7570
|
+
(app2, deps) => registerLarkChannelRoutes(app2, deps),
|
|
7571
|
+
(app2, _deps) => registerWechatChannelRoutes(app2)
|
|
7137
7572
|
];
|
|
7138
7573
|
function registerChannelRoutes(app2, dependencies) {
|
|
7139
7574
|
if (!dependencies) return;
|
|
@@ -7144,6 +7579,12 @@ function registerChannelRoutes(app2, dependencies) {
|
|
|
7144
7579
|
|
|
7145
7580
|
// src/controllers/channel-installations.ts
|
|
7146
7581
|
var import_crypto8 = require("crypto");
|
|
7582
|
+
var _adapterRegistry;
|
|
7583
|
+
var _router;
|
|
7584
|
+
function setChannelControllerDeps(deps) {
|
|
7585
|
+
_adapterRegistry = deps.adapterRegistry;
|
|
7586
|
+
_router = deps.router;
|
|
7587
|
+
}
|
|
7147
7588
|
function getTenantId13(request) {
|
|
7148
7589
|
const userTenantId = request.user?.tenantId;
|
|
7149
7590
|
if (userTenantId) {
|
|
@@ -7153,8 +7594,8 @@ function getTenantId13(request) {
|
|
|
7153
7594
|
}
|
|
7154
7595
|
async function getInstallationStore() {
|
|
7155
7596
|
const { getStoreLattice: getStoreLattice18 } = await import("@axiom-lattice/core");
|
|
7156
|
-
const
|
|
7157
|
-
if (
|
|
7597
|
+
const store2 = getStoreLattice18("default", "channelInstallation").store;
|
|
7598
|
+
if (store2) return store2;
|
|
7158
7599
|
const { PostgreSQLChannelInstallationStore } = await import("@axiom-lattice/pg-stores");
|
|
7159
7600
|
const databaseUrl = process.env.DATABASE_URL;
|
|
7160
7601
|
if (!databaseUrl) {
|
|
@@ -7168,8 +7609,8 @@ async function getChannelInstallationList(request, reply) {
|
|
|
7168
7609
|
const tenantId = getTenantId13(request);
|
|
7169
7610
|
const { channel } = request.query;
|
|
7170
7611
|
try {
|
|
7171
|
-
const
|
|
7172
|
-
const installations = await
|
|
7612
|
+
const store2 = await getInstallationStore();
|
|
7613
|
+
const installations = await store2.getInstallationsByTenant(tenantId, channel);
|
|
7173
7614
|
return {
|
|
7174
7615
|
success: true,
|
|
7175
7616
|
message: "Channel installations retrieved successfully",
|
|
@@ -7194,8 +7635,8 @@ async function getChannelInstallation(request, reply) {
|
|
|
7194
7635
|
const tenantId = getTenantId13(request);
|
|
7195
7636
|
const { installationId } = request.params;
|
|
7196
7637
|
try {
|
|
7197
|
-
const
|
|
7198
|
-
const installation = await
|
|
7638
|
+
const store2 = await getInstallationStore();
|
|
7639
|
+
const installation = await store2.getInstallationById(installationId);
|
|
7199
7640
|
if (!installation) {
|
|
7200
7641
|
reply.code(404);
|
|
7201
7642
|
return {
|
|
@@ -7258,13 +7699,23 @@ async function createChannelInstallation(request, reply) {
|
|
|
7258
7699
|
};
|
|
7259
7700
|
}
|
|
7260
7701
|
}
|
|
7261
|
-
const
|
|
7702
|
+
const store2 = await getInstallationStore();
|
|
7262
7703
|
const installationId = body.id || (0, import_crypto8.randomUUID)();
|
|
7263
|
-
const installation = await
|
|
7704
|
+
const installation = await store2.createInstallation(
|
|
7264
7705
|
tenantId,
|
|
7265
7706
|
installationId,
|
|
7266
7707
|
body
|
|
7267
7708
|
);
|
|
7709
|
+
if (body.enabled !== false && _adapterRegistry) {
|
|
7710
|
+
const adapter = _adapterRegistry.get(body.channel);
|
|
7711
|
+
if (adapter?.connect) {
|
|
7712
|
+
try {
|
|
7713
|
+
await adapter.connect(installation, { router: _router });
|
|
7714
|
+
} catch (err) {
|
|
7715
|
+
console.error("Failed to start channel connection after creation:", err);
|
|
7716
|
+
}
|
|
7717
|
+
}
|
|
7718
|
+
}
|
|
7268
7719
|
reply.code(201);
|
|
7269
7720
|
return {
|
|
7270
7721
|
success: true,
|
|
@@ -7291,8 +7742,8 @@ async function updateChannelInstallation(request, reply) {
|
|
|
7291
7742
|
const { installationId } = request.params;
|
|
7292
7743
|
const body = request.body;
|
|
7293
7744
|
try {
|
|
7294
|
-
const
|
|
7295
|
-
const existing = await
|
|
7745
|
+
const store2 = await getInstallationStore();
|
|
7746
|
+
const existing = await store2.getInstallationById(installationId);
|
|
7296
7747
|
if (!existing) {
|
|
7297
7748
|
reply.code(404);
|
|
7298
7749
|
return {
|
|
@@ -7307,7 +7758,7 @@ async function updateChannelInstallation(request, reply) {
|
|
|
7307
7758
|
message: "Access denied"
|
|
7308
7759
|
};
|
|
7309
7760
|
}
|
|
7310
|
-
const installation = await
|
|
7761
|
+
const installation = await store2.updateInstallation(
|
|
7311
7762
|
tenantId,
|
|
7312
7763
|
installationId,
|
|
7313
7764
|
body
|
|
@@ -7319,6 +7770,14 @@ async function updateChannelInstallation(request, reply) {
|
|
|
7319
7770
|
message: "Channel installation not found"
|
|
7320
7771
|
};
|
|
7321
7772
|
}
|
|
7773
|
+
if (body.enabled !== void 0 && body.enabled !== existing.enabled) {
|
|
7774
|
+
const adapter = _adapterRegistry?.get(existing.channel);
|
|
7775
|
+
if (body.enabled && adapter?.connect) {
|
|
7776
|
+
await adapter.connect(installation, { router: _router });
|
|
7777
|
+
} else if (!body.enabled && adapter?.disconnect) {
|
|
7778
|
+
await adapter.disconnect(installationId);
|
|
7779
|
+
}
|
|
7780
|
+
}
|
|
7322
7781
|
return {
|
|
7323
7782
|
success: true,
|
|
7324
7783
|
message: "Channel installation updated successfully",
|
|
@@ -7336,8 +7795,8 @@ async function deleteChannelInstallation(request, reply) {
|
|
|
7336
7795
|
const tenantId = getTenantId13(request);
|
|
7337
7796
|
const { installationId } = request.params;
|
|
7338
7797
|
try {
|
|
7339
|
-
const
|
|
7340
|
-
const existing = await
|
|
7798
|
+
const store2 = await getInstallationStore();
|
|
7799
|
+
const existing = await store2.getInstallationById(installationId);
|
|
7341
7800
|
if (!existing) {
|
|
7342
7801
|
reply.code(404);
|
|
7343
7802
|
return {
|
|
@@ -7352,7 +7811,17 @@ async function deleteChannelInstallation(request, reply) {
|
|
|
7352
7811
|
message: "Access denied"
|
|
7353
7812
|
};
|
|
7354
7813
|
}
|
|
7355
|
-
|
|
7814
|
+
if (_adapterRegistry) {
|
|
7815
|
+
const adapter = _adapterRegistry.get(existing.channel);
|
|
7816
|
+
if (adapter?.disconnect) {
|
|
7817
|
+
try {
|
|
7818
|
+
await adapter.disconnect(installationId);
|
|
7819
|
+
} catch (err) {
|
|
7820
|
+
console.error("Failed to disconnect channel adapter:", err);
|
|
7821
|
+
}
|
|
7822
|
+
}
|
|
7823
|
+
}
|
|
7824
|
+
const deleted = await store2.deleteInstallation(tenantId, installationId);
|
|
7356
7825
|
if (!deleted) {
|
|
7357
7826
|
reply.code(404);
|
|
7358
7827
|
return {
|
|
@@ -8442,6 +8911,7 @@ function createRateLimitMiddleware(maxRequests = 10, windowMs = 60 * 1e3, maxEnt
|
|
|
8442
8911
|
}
|
|
8443
8912
|
|
|
8444
8913
|
// src/router/middlewares/auditLogger.ts
|
|
8914
|
+
init_Logger();
|
|
8445
8915
|
var logger3 = new Logger({ serviceName: "lattice/gateway/audit" });
|
|
8446
8916
|
function createAuditLoggerMiddleware() {
|
|
8447
8917
|
return async (ctx, next) => {
|
|
@@ -8805,7 +9275,7 @@ var DEFAULT_LOGGER_CONFIG = {
|
|
|
8805
9275
|
loggerName: "lattice/gateway"
|
|
8806
9276
|
};
|
|
8807
9277
|
var loggerLattice = initializeLogger(DEFAULT_LOGGER_CONFIG);
|
|
8808
|
-
var
|
|
9278
|
+
var logger5 = loggerLattice.client;
|
|
8809
9279
|
function initializeLogger(config) {
|
|
8810
9280
|
if (import_core36.loggerLatticeManager.hasLattice("default")) {
|
|
8811
9281
|
import_core36.loggerLatticeManager.removeLattice("default");
|
|
@@ -8906,7 +9376,7 @@ app.setErrorHandler((error, request, reply) => {
|
|
|
8906
9376
|
"x-request-id": getHeaderValue(request.headers["x-request-id"]),
|
|
8907
9377
|
"x-user-id": getHeaderValue(request.headers["x-user-id"])
|
|
8908
9378
|
};
|
|
8909
|
-
|
|
9379
|
+
logger5.error(
|
|
8910
9380
|
`\u8BF7\u6C42\u9519\u8BEF: ${request.method} ${request.url} error:${error.message}`,
|
|
8911
9381
|
{
|
|
8912
9382
|
...context,
|
|
@@ -8946,18 +9416,18 @@ var start = async (config) => {
|
|
|
8946
9416
|
file: config.loggerConfig.file || DEFAULT_LOGGER_CONFIG.file
|
|
8947
9417
|
};
|
|
8948
9418
|
loggerLattice = initializeLogger(loggerConfig);
|
|
8949
|
-
|
|
9419
|
+
logger5 = loggerLattice.client;
|
|
8950
9420
|
}
|
|
8951
9421
|
app.decorate("loggerLattice", loggerLattice);
|
|
8952
9422
|
let channelDeps;
|
|
8953
9423
|
const adapterRegistry = new ChannelAdapterRegistry();
|
|
8954
9424
|
adapterRegistry.register(larkChannelAdapter);
|
|
9425
|
+
const { wechatChannelAdapter: wechatChannelAdapter2 } = await Promise.resolve().then(() => (init_WechatChannelAdapter(), WechatChannelAdapter_exports));
|
|
9426
|
+
adapterRegistry.register(wechatChannelAdapter2);
|
|
8955
9427
|
try {
|
|
8956
9428
|
const { getStoreLattice: getStore2 } = await import("@axiom-lattice/core");
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
bindingStore = getStore2("default", "channelBinding").store;
|
|
8960
|
-
installationStore = getStore2("default", "channelInstallation").store;
|
|
9429
|
+
const bindingStore = getStore2("default", "channelBinding").store;
|
|
9430
|
+
const installationStore = getStore2("default", "channelInstallation").store;
|
|
8961
9431
|
(0, import_core35.setBindingRegistry)(bindingStore);
|
|
8962
9432
|
const router = new MessageRouter({
|
|
8963
9433
|
middlewares: [
|
|
@@ -8975,24 +9445,27 @@ var start = async (config) => {
|
|
|
8975
9445
|
const a2a = await Promise.resolve().then(() => (init_a2a(), a2a_exports));
|
|
8976
9446
|
a2a.setA2AKeyStore(a2aKeyStore);
|
|
8977
9447
|
await a2a.refreshStoreKeyMap();
|
|
8978
|
-
|
|
9448
|
+
logger5.info("A2A key store initialized");
|
|
8979
9449
|
} catch {
|
|
8980
9450
|
}
|
|
8981
9451
|
} catch (err) {
|
|
8982
|
-
|
|
9452
|
+
logger5.warn("Channel infrastructure unavailable", {
|
|
8983
9453
|
error: err instanceof Error ? err.message : String(err)
|
|
8984
9454
|
});
|
|
8985
9455
|
}
|
|
8986
9456
|
try {
|
|
8987
9457
|
const menuStore = (0, import_core36.getStoreLattice)("default", "menu").store;
|
|
8988
9458
|
(0, import_core35.setMenuRegistry)(menuStore);
|
|
8989
|
-
|
|
9459
|
+
logger5.info("Menu registry initialized");
|
|
8990
9460
|
} catch {
|
|
8991
9461
|
}
|
|
9462
|
+
if (channelDeps?.router) {
|
|
9463
|
+
setChannelControllerDeps({ adapterRegistry, router: channelDeps.router });
|
|
9464
|
+
}
|
|
8992
9465
|
registerLatticeRoutes(app, channelDeps);
|
|
8993
9466
|
if (!import_core36.sandboxLatticeManager.hasLattice("default")) {
|
|
8994
9467
|
import_core36.sandboxLatticeManager.registerLattice("default", getConfiguredSandboxProvider());
|
|
8995
|
-
|
|
9468
|
+
logger5.info("Registered sandbox manager from env configuration");
|
|
8996
9469
|
}
|
|
8997
9470
|
if (channelDeps && process.env.CHANNELS_ENABLED !== "false") {
|
|
8998
9471
|
const { connectAllChannels } = await import("@axiom-lattice/core");
|
|
@@ -9002,18 +9475,18 @@ var start = async (config) => {
|
|
|
9002
9475
|
{ deps: { router: channelDeps.router } }
|
|
9003
9476
|
);
|
|
9004
9477
|
} catch (err) {
|
|
9005
|
-
|
|
9478
|
+
logger5.error("Failed to start channel connections", {
|
|
9006
9479
|
error: err instanceof Error ? err.message : String(err)
|
|
9007
9480
|
});
|
|
9008
9481
|
}
|
|
9009
9482
|
}
|
|
9010
9483
|
const target_port = config?.port || Number(process.env.PORT) || 4001;
|
|
9011
9484
|
await app.listen({ port: target_port, host: "0.0.0.0" });
|
|
9012
|
-
|
|
9485
|
+
logger5.info(`Lattice Gateway is running on port: ${target_port}`);
|
|
9013
9486
|
try {
|
|
9014
|
-
|
|
9487
|
+
logger5.info("AgentLifecycleManager initialized");
|
|
9015
9488
|
} catch (error) {
|
|
9016
|
-
|
|
9489
|
+
logger5.warn("Failed to initialize AgentLifecycleManager", { error });
|
|
9017
9490
|
}
|
|
9018
9491
|
const queueServiceConfig = config?.queueServiceConfig;
|
|
9019
9492
|
if (queueServiceConfig) {
|
|
@@ -9024,12 +9497,12 @@ var start = async (config) => {
|
|
|
9024
9497
|
}
|
|
9025
9498
|
}
|
|
9026
9499
|
import_core36.agentInstanceManager.restore().then((stats) => {
|
|
9027
|
-
|
|
9500
|
+
logger5.info(`Agent recovery complete: ${stats.restored} threads restored, ${stats.errors} errors`);
|
|
9028
9501
|
}).catch((error) => {
|
|
9029
|
-
|
|
9502
|
+
logger5.error("Agent recovery failed", { error });
|
|
9030
9503
|
});
|
|
9031
9504
|
} catch (err) {
|
|
9032
|
-
|
|
9505
|
+
logger5.error("Server start failed", { error: err });
|
|
9033
9506
|
process.exit(1);
|
|
9034
9507
|
}
|
|
9035
9508
|
};
|